From 6a6df2d9113856a4371ca4f1cb29221790320307 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: Partially revert "staging:iio:gyro:adxrs450 make more use of spi_read and spi_write." This partially reverts commit cb4496876f03631eff913b3c608c964d48d61eb9. There is no apparent reason why we should split a transaction which consists out of multiple transfers into multiple transactions each having one transfer. While this works it introduces a bunch of unnecessary context switch and additional setup costs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 48 ++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 14 deletions(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index f0ce81da8aca..318e8c9c6544 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -34,8 +34,21 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, u8 reg_address, u16 *val) { + struct spi_message msg; struct adxrs450_state *st = iio_priv(indio_dev); int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 4, + .cs_change = 1, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }, + }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_READ_DATA | (reg_address >> 7); @@ -46,13 +59,10 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) st->tx[3] |= ADXRS450_P; - ret = spi_write(st->us, st->tx, 4); - if (ret) { - dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", - reg_address); - goto error_ret; - } - ret = spi_read(st->us, st->rx, 4); + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); if (ret) { dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", reg_address); @@ -105,8 +115,21 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, **/ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) { + struct spi_message msg; struct adxrs450_state *st = iio_priv(indio_dev); int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 4, + .cs_change = 1, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }, + }; mutex_lock(&st->buf_lock); st->tx[0] = ADXRS450_SENSOR_DATA; @@ -114,13 +137,10 @@ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) st->tx[2] = 0; st->tx[3] = 0; - ret = spi_write(st->us, st->tx, 4); - if (ret) { - dev_err(&st->us->dev, "Problem while reading sensor data\n"); - goto error_ret; - } - - ret = spi_read(st->us, st->rx, 4); + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); if (ret) { dev_err(&st->us->dev, "Problem while reading sensor data\n"); goto error_ret; -- cgit v1.2.3 From 1a87e4fba63cd82d74f23b6e0b75ad6b01b15774 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Make transfer buffers __be32 Fixes the following sparse warnings: drivers/staging/iio/gyro/adxrs450_core.c:46:15: warning: cast to restricted __be32 drivers/staging/iio/gyro/adxrs450_core.c:62:17: warning: cast to restricted __be32 drivers/staging/iio/gyro/adxrs450_core.c:89:15: warning: cast to restricted __be32 drivers/staging/iio/gyro/adxrs450_core.c:129:17: warning: cast to restricted __be32 drivers/staging/iio/gyro/adxrs450_core.c:168:16: warning: cast to restricted __be32 Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450.h | 10 ++--- drivers/staging/iio/gyro/adxrs450_core.c | 66 +++++++++++++++----------------- 2 files changed, 35 insertions(+), 41 deletions(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450.h b/drivers/staging/iio/gyro/adxrs450.h index f8cf21f02943..97abea32f220 100644 --- a/drivers/staging/iio/gyro/adxrs450.h +++ b/drivers/staging/iio/gyro/adxrs450.h @@ -4,9 +4,9 @@ #define ADXRS450_STARTUP_DELAY 50 /* ms */ /* The MSB for the spi commands */ -#define ADXRS450_SENSOR_DATA 0x20 -#define ADXRS450_WRITE_DATA 0x40 -#define ADXRS450_READ_DATA 0x80 +#define ADXRS450_SENSOR_DATA (0x20 << 24) +#define ADXRS450_WRITE_DATA (0x40 << 24) +#define ADXRS450_READ_DATA (0x80 << 24) #define ADXRS450_RATE1 0x00 /* Rate Registers */ #define ADXRS450_TEMP1 0x02 /* Temperature Registers */ @@ -54,8 +54,8 @@ enum { struct adxrs450_state { struct spi_device *us; struct mutex buf_lock; - u8 tx[ADXRS450_MAX_RX] ____cacheline_aligned; - u8 rx[ADXRS450_MAX_TX]; + __be32 tx ____cacheline_aligned; + __be32 rx; }; diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 318e8c9c6544..91a2fae1abbe 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -36,29 +36,28 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, { struct spi_message msg; struct adxrs450_state *st = iio_priv(indio_dev); + u32 tx; int ret; struct spi_transfer xfers[] = { { - .tx_buf = st->tx, + .tx_buf = &st->tx, .bits_per_word = 8, - .len = 4, + .len = sizeof(st->tx), .cs_change = 1, }, { - .rx_buf = st->rx, + .rx_buf = &st->rx, .bits_per_word = 8, - .len = 4, + .len = sizeof(st->rx), }, }; mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_READ_DATA | (reg_address >> 7); - st->tx[1] = reg_address << 1; - st->tx[2] = 0; - st->tx[3] = 0; + tx = ADXRS450_READ_DATA | (reg_address << 17); - if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) - st->tx[3] |= ADXRS450_P; + if (!(hweight32(tx) & 1)) + tx |= ADXRS450_P; + st->tx = cpu_to_be32(tx); spi_message_init(&msg); spi_message_add_tail(&xfers[0], &msg); spi_message_add_tail(&xfers[1], &msg); @@ -69,7 +68,7 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, goto error_ret; } - *val = (be32_to_cpu(*(u32 *)st->rx) >> 5) & 0xFFFF; + *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF; error_ret: mutex_unlock(&st->buf_lock); @@ -88,18 +87,17 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, u16 val) { struct adxrs450_state *st = iio_priv(indio_dev); + u32 tx; int ret; mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_WRITE_DATA | reg_address >> 7; - st->tx[1] = reg_address << 1 | val >> 15; - st->tx[2] = val >> 7; - st->tx[3] = val << 1; + tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1); - if (!(hweight32(be32_to_cpu(*(u32 *)st->tx)) & 1)) - st->tx[3] |= ADXRS450_P; + if (!(hweight32(tx) & 1)) + tx |= ADXRS450_P; - ret = spi_write(st->us, st->tx, 4); + st->tx = cpu_to_be32(tx); + ret = spi_write(st->us, &st->tx, sizeof(st->tx)); if (ret) dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", reg_address); @@ -120,22 +118,19 @@ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) int ret; struct spi_transfer xfers[] = { { - .tx_buf = st->tx, + .tx_buf = &st->tx, .bits_per_word = 8, - .len = 4, + .len = sizeof(st->tx), .cs_change = 1, }, { - .rx_buf = st->rx, + .rx_buf = &st->rx, .bits_per_word = 8, - .len = 4, + .len = sizeof(st->rx), }, }; mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_SENSOR_DATA; - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; + st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); spi_message_init(&msg); spi_message_add_tail(&xfers[0], &msg); @@ -146,7 +141,7 @@ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) goto error_ret; } - *val = (be32_to_cpu(*(u32 *)st->rx) >> 10) & 0xFFFF; + *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF; error_ret: mutex_unlock(&st->buf_lock); @@ -163,20 +158,19 @@ static int adxrs450_spi_initial(struct adxrs450_state *st, { struct spi_message msg; int ret; + u32 tx; struct spi_transfer xfers = { - .tx_buf = st->tx, - .rx_buf = st->rx, + .tx_buf = &st->tx, + .rx_buf = &st->rx, .bits_per_word = 8, - .len = 4, + .len = sizeof(st->tx), }; mutex_lock(&st->buf_lock); - st->tx[0] = ADXRS450_SENSOR_DATA; - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 0; + tx = ADXRS450_SENSOR_DATA; if (chk) - st->tx[3] |= (ADXRS450_CHK | ADXRS450_P); + tx |= (ADXRS450_CHK | ADXRS450_P); + st->tx = cpu_to_be32(tx); spi_message_init(&msg); spi_message_add_tail(&xfers, &msg); ret = spi_sync(st->us, &msg); @@ -185,7 +179,7 @@ static int adxrs450_spi_initial(struct adxrs450_state *st, goto error_ret; } - *val = be32_to_cpu(*(u32 *)st->rx); + *val = be32_to_cpu(st->rx); error_ret: mutex_unlock(&st->buf_lock); -- cgit v1.2.3 From c62b89c713ebd5e4a67c9b9229591adab8953a3c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Perform sign extension for the calibbias register The calibbias (DNC) register contains a 10-bit twos complement value. Perform a proper sign extension when reading the register, otherwise negative will incorrectly be displayed as large positive values. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 91a2fae1abbe..4c462d36dac9 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -326,7 +326,7 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev, ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); if (ret) break; - *val = t; + *val = sign_extend32(t, 9); ret = IIO_VAL_INT; break; default: -- cgit v1.2.3 From 9a26578c811e6f4de24d81ef734b17c401e5080f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Reject out of range calibscale values Instead of silently discarding the upper bits reject out of range values for the calibscale property. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 4c462d36dac9..96e52844377b 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -258,9 +258,10 @@ static int adxrs450_write_raw(struct iio_dev *indio_dev, int ret; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: + if (val < -0x400 || val >= 0x400) + return -EINVAL; ret = adxrs450_spi_write_reg_16(indio_dev, - ADXRS450_DNC1, - val & 0x3FF); + ADXRS450_DNC1, val); break; default: ret = -EINVAL; -- cgit v1.2.3 From ceac0cf209842e49c277ac301d4ce69b4db8239b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Don't spam the bootlog Don't spam the bootlog with the devices part id and serial number. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 96e52844377b..24b7a0f6f1fd 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -231,20 +231,6 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev) dev_err(&st->us->dev, "The device is not in normal status!\n"); return -EINVAL; } - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_PID1, &data); - if (ret) - return ret; - dev_info(&st->us->dev, "The Part ID is 0x%x\n", data); - - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNL, &data); - if (ret) - return ret; - t = data; - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_SNH, &data); - if (ret) - return ret; - t |= data << 16; - dev_info(&st->us->dev, "The Serial Number is 0x%x\n", t); return 0; } -- cgit v1.2.3 From 1439b6e8d1a1b158c11ecf398dd9bf3fcceb4861 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Reflow overlong lines Reflow two lines to meet the 80 characters per line limit. Fixes the following checkpatch warnings: WARNING: line over 80 characters #29: FILE: staging/iio/gyro/adxrs450_core.c:29: + * @reg_address: the address of the lower of the two registers,which should be an even address, WARNING: line over 80 characters #81: FILE: staging/iio/gyro/adxrs450_core.c:81: + * @reg_address: the address of the lower of the two registers,which should be an even address, Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 24b7a0f6f1fd..dd0b7447d098 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -26,8 +26,8 @@ /** * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair * @dev: device associated with child of actual iio_dev - * @reg_address: the address of the lower of the two registers,which should be an even address, - * Second register's address is reg_address + 1. + * @reg_address: the address of the lower of the two registers, which should be + * an even address, the second register's address is reg_address + 1. * @val: somewhere to pass back the value read **/ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, @@ -78,8 +78,8 @@ error_ret: /** * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair * @dev: device associated with child of actual actual iio_dev - * @reg_address: the address of the lower of the two registers,which should be an even address, - * Second register's address is reg_address + 1. + * @reg_address: the address of the lower of the two registers,which should be + * an even address, the second register's address is reg_address + 1. * @val: value to be written. **/ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, -- cgit v1.2.3 From 457b71df27e4e6125b6627ad3d4ae1da023fc908 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Don't split string across multiple lines This is one of the exceptions to the 80 chars per line rule since breaking the string in half it badly affects the grep-ability. Fixes the following checkpatch warning: WARNING: quoted string split across lines #203: FILE: staging/iio/gyro/adxrs450_core.c:203: + dev_warn(&st->us->dev, "The initial power on response " + "is not correct! Restart without reset?\n"); Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index dd0b7447d098..ea10f84cee17 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -199,8 +199,7 @@ static int adxrs450_initial_setup(struct iio_dev *indio_dev) if (ret) return ret; if (t != 0x01) - dev_warn(&st->us->dev, "The initial power on response " - "is not correct! Restart without reset?\n"); + dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n"); msleep(ADXRS450_STARTUP_DELAY); ret = adxrs450_spi_initial(st, &t, 0); -- cgit v1.2.3 From 619036e216ce4d34f6d51ad2cf50380a54734c18 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Use usleep_range for the sequential transfer dealy The adxrs450 requires a delay of at least 0.1 ms between register writes. Using msleep() for such small delays is not recommended. So use usleep_range instead. Fixes the following checkpatch warning: WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index ea10f84cee17..4115fe145137 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -101,7 +101,7 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, if (ret) dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", reg_address); - msleep(1); /* enforce sequential transfer delay 0.1ms */ + usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */ mutex_unlock(&st->buf_lock); return ret; } -- cgit v1.2.3 From d5e69c8350bbcf3c6058b0aceff32a2f2972485e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Fixup kernel doc comments Fix the name of the iio_device parameter for a few functions and add documentation for one missing function parameter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/adxrs450_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 4115fe145137..714e3239d5d6 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -25,7 +25,7 @@ /** * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair - * @dev: device associated with child of actual iio_dev + * @indio_dev: device associated with child of actual iio_dev * @reg_address: the address of the lower of the two registers, which should be * an even address, the second register's address is reg_address + 1. * @val: somewhere to pass back the value read @@ -77,7 +77,7 @@ error_ret: /** * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair - * @dev: device associated with child of actual actual iio_dev + * @indio_dev: device associated with child of actual actual iio_dev * @reg_address: the address of the lower of the two registers,which should be * an even address, the second register's address is reg_address + 1. * @val: value to be written. @@ -108,7 +108,7 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, /** * adxrs450_spi_sensor_data() - read 2 bytes sensor data - * @dev: device associated with child of actual iio_dev + * @indio_dev: device associated with child of actual iio_dev * @val: somewhere to pass back the value read **/ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) @@ -152,6 +152,7 @@ error_ret: * adxrs450_spi_initial() - use for initializing procedure. * @st: device instance specific data * @val: somewhere to pass back the value read + * @chk: Whether to perform fault check **/ static int adxrs450_spi_initial(struct adxrs450_state *st, u32 *val, char chk) -- cgit v1.2.3 From 53ac8500ba9badae82b0412d08e1db9f5b21b3d5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio:adxrs450: Move header file contents to main file The contents of the adxrs450 header file is not used outside the main drivers file, so just move the contents from the header file into the drivers main file. Also rename the adxrs450 driver file from adxrs450_core.c to adxrs450.c. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/gyro/Makefile | 1 - drivers/staging/iio/gyro/adxrs450.c | 497 +++++++++++++++++++++++++++++++ drivers/staging/iio/gyro/adxrs450.h | 62 ---- drivers/staging/iio/gyro/adxrs450_core.c | 441 --------------------------- 4 files changed, 497 insertions(+), 504 deletions(-) create mode 100644 drivers/staging/iio/gyro/adxrs450.c delete mode 100644 drivers/staging/iio/gyro/adxrs450.h delete mode 100644 drivers/staging/iio/gyro/adxrs450_core.c (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile index ef3316171299..6b4e60ab743f 100644 --- a/drivers/staging/iio/gyro/Makefile +++ b/drivers/staging/iio/gyro/Makefile @@ -11,5 +11,4 @@ obj-$(CONFIG_ADIS16130) += adis16130.o adis16260-y := adis16260_core.o obj-$(CONFIG_ADIS16260) += adis16260.o -adxrs450-y := adxrs450_core.o obj-$(CONFIG_ADXRS450) += adxrs450.o diff --git a/drivers/staging/iio/gyro/adxrs450.c b/drivers/staging/iio/gyro/adxrs450.c new file mode 100644 index 000000000000..d9d43831c380 --- /dev/null +++ b/drivers/staging/iio/gyro/adxrs450.c @@ -0,0 +1,497 @@ +/* + * ADXRS450/ADXRS453 Digital Output Gyroscope Driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define ADXRS450_STARTUP_DELAY 50 /* ms */ + +/* The MSB for the spi commands */ +#define ADXRS450_SENSOR_DATA (0x20 << 24) +#define ADXRS450_WRITE_DATA (0x40 << 24) +#define ADXRS450_READ_DATA (0x80 << 24) + +#define ADXRS450_RATE1 0x00 /* Rate Registers */ +#define ADXRS450_TEMP1 0x02 /* Temperature Registers */ +#define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */ +#define ADXRS450_HICST1 0x06 /* High CST Memory Registers */ +#define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */ +#define ADXRS450_FAULT1 0x0A /* Fault Registers */ +#define ADXRS450_PID1 0x0C /* Part ID Register 1 */ +#define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */ +#define ADXRS450_SNL 0x10 +#define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */ +/* Check bits */ +#define ADXRS450_P 0x01 +#define ADXRS450_CHK 0x02 +#define ADXRS450_CST 0x04 +#define ADXRS450_PWR 0x08 +#define ADXRS450_POR 0x10 +#define ADXRS450_NVM 0x20 +#define ADXRS450_Q 0x40 +#define ADXRS450_PLL 0x80 +#define ADXRS450_UV 0x100 +#define ADXRS450_OV 0x200 +#define ADXRS450_AMP 0x400 +#define ADXRS450_FAIL 0x800 + +#define ADXRS450_WRERR_MASK (0x7 << 29) + +#define ADXRS450_MAX_RX 4 +#define ADXRS450_MAX_TX 4 + +#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3) + +enum { + ID_ADXRS450, + ID_ADXRS453, +}; + +/** + * struct adxrs450_state - device instance specific data + * @us: actual spi_device + * @buf_lock: mutex to protect tx and rx + * @tx: transmit buffer + * @rx: receive buffer + **/ +struct adxrs450_state { + struct spi_device *us; + struct mutex buf_lock; + __be32 tx ____cacheline_aligned; + __be32 rx; + +}; + +/** + * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair + * @indio_dev: device associated with child of actual iio_dev + * @reg_address: the address of the lower of the two registers, which should be + * an even address, the second register's address is reg_address + 1. + * @val: somewhere to pass back the value read + **/ +static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, + u8 reg_address, + u16 *val) +{ + struct spi_message msg; + struct adxrs450_state *st = iio_priv(indio_dev); + u32 tx; + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = &st->tx, + .bits_per_word = 8, + .len = sizeof(st->tx), + .cs_change = 1, + }, { + .rx_buf = &st->rx, + .bits_per_word = 8, + .len = sizeof(st->rx), + }, + }; + + mutex_lock(&st->buf_lock); + tx = ADXRS450_READ_DATA | (reg_address << 17); + + if (!(hweight32(tx) & 1)) + tx |= ADXRS450_P; + + st->tx = cpu_to_be32(tx); + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", + reg_address); + goto error_ret; + } + + *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair + * @indio_dev: device associated with child of actual actual iio_dev + * @reg_address: the address of the lower of the two registers,which should be + * an even address, the second register's address is reg_address + 1. + * @val: value to be written. + **/ +static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, + u8 reg_address, + u16 val) +{ + struct adxrs450_state *st = iio_priv(indio_dev); + u32 tx; + int ret; + + mutex_lock(&st->buf_lock); + tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1); + + if (!(hweight32(tx) & 1)) + tx |= ADXRS450_P; + + st->tx = cpu_to_be32(tx); + ret = spi_write(st->us, &st->tx, sizeof(st->tx)); + if (ret) + dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", + reg_address); + usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */ + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adxrs450_spi_sensor_data() - read 2 bytes sensor data + * @indio_dev: device associated with child of actual iio_dev + * @val: somewhere to pass back the value read + **/ +static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) +{ + struct spi_message msg; + struct adxrs450_state *st = iio_priv(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = &st->tx, + .bits_per_word = 8, + .len = sizeof(st->tx), + .cs_change = 1, + }, { + .rx_buf = &st->rx, + .bits_per_word = 8, + .len = sizeof(st->rx), + }, + }; + + mutex_lock(&st->buf_lock); + st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "Problem while reading sensor data\n"); + goto error_ret; + } + + *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adxrs450_spi_initial() - use for initializing procedure. + * @st: device instance specific data + * @val: somewhere to pass back the value read + * @chk: Whether to perform fault check + **/ +static int adxrs450_spi_initial(struct adxrs450_state *st, + u32 *val, char chk) +{ + struct spi_message msg; + int ret; + u32 tx; + struct spi_transfer xfers = { + .tx_buf = &st->tx, + .rx_buf = &st->rx, + .bits_per_word = 8, + .len = sizeof(st->tx), + }; + + mutex_lock(&st->buf_lock); + tx = ADXRS450_SENSOR_DATA; + if (chk) + tx |= (ADXRS450_CHK | ADXRS450_P); + st->tx = cpu_to_be32(tx); + spi_message_init(&msg); + spi_message_add_tail(&xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "Problem while reading initializing data\n"); + goto error_ret; + } + + *val = be32_to_cpu(st->rx); + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +/* Recommended Startup Sequence by spec */ +static int adxrs450_initial_setup(struct iio_dev *indio_dev) +{ + u32 t; + u16 data; + int ret; + struct adxrs450_state *st = iio_priv(indio_dev); + + msleep(ADXRS450_STARTUP_DELAY*2); + ret = adxrs450_spi_initial(st, &t, 1); + if (ret) + return ret; + if (t != 0x01) + dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n"); + + msleep(ADXRS450_STARTUP_DELAY); + ret = adxrs450_spi_initial(st, &t, 0); + if (ret) + return ret; + + msleep(ADXRS450_STARTUP_DELAY); + ret = adxrs450_spi_initial(st, &t, 0); + if (ret) + return ret; + if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { + dev_err(&st->us->dev, "The second response is not correct!\n"); + return -EIO; + + } + ret = adxrs450_spi_initial(st, &t, 0); + if (ret) + return ret; + if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { + dev_err(&st->us->dev, "The third response is not correct!\n"); + return -EIO; + + } + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); + if (ret) + return ret; + if (data & 0x0fff) { + dev_err(&st->us->dev, "The device is not in normal status!\n"); + return -EINVAL; + } + + return 0; +} + +static int adxrs450_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int ret; + switch (mask) { + case IIO_CHAN_INFO_CALIBBIAS: + if (val < -0x400 || val >= 0x400) + return -EINVAL; + ret = adxrs450_spi_write_reg_16(indio_dev, + ADXRS450_DNC1, val); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int adxrs450_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + s16 t; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ANGL_VEL: + ret = adxrs450_spi_sensor_data(indio_dev, &t); + if (ret) + break; + *val = t; + ret = IIO_VAL_INT; + break; + case IIO_TEMP: + ret = adxrs450_spi_read_reg_16(indio_dev, + ADXRS450_TEMP1, &t); + if (ret) + break; + *val = (t >> 6) + 225; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = 0; + *val2 = 218166; + return IIO_VAL_INT_PLUS_NANO; + case IIO_TEMP: + *val = 200; + *val2 = 0; + return IIO_VAL_INT; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); + if (ret) + break; + *val = t; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_CALIBBIAS: + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); + if (ret) + break; + *val = sign_extend32(t, 9); + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const struct iio_chan_spec adxrs450_channels[2][2] = { + [ID_ADXRS450] = { + { + .type = IIO_ANGL_VEL, + .modified = 1, + .channel2 = IIO_MOD_Z, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + } + }, + [ID_ADXRS453] = { + { + .type = IIO_ANGL_VEL, + .modified = 1, + .channel2 = IIO_MOD_Z, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT, + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + } + }, +}; + +static const struct iio_info adxrs450_info = { + .driver_module = THIS_MODULE, + .read_raw = &adxrs450_read_raw, + .write_raw = &adxrs450_write_raw, +}; + +static int adxrs450_probe(struct spi_device *spi) +{ + int ret; + struct adxrs450_state *st; + struct iio_dev *indio_dev; + + /* setup the industrialio driver allocated elements */ + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + st = iio_priv(indio_dev); + st->us = spi; + mutex_init(&st->buf_lock); + /* This is only used for removal purposes */ + spi_set_drvdata(spi, indio_dev); + + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &adxrs450_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = + adxrs450_channels[spi_get_device_id(spi)->driver_data]; + indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); + indio_dev->name = spi->dev.driver->name; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_dev; + + /* Get the device into a sane initial state */ + ret = adxrs450_initial_setup(indio_dev); + if (ret) + goto error_initial; + return 0; +error_initial: + iio_device_unregister(indio_dev); +error_free_dev: + iio_device_free(indio_dev); + +error_ret: + return ret; +} + +static int adxrs450_remove(struct spi_device *spi) +{ + iio_device_unregister(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); + + return 0; +} + +static const struct spi_device_id adxrs450_id[] = { + {"adxrs450", ID_ADXRS450}, + {"adxrs453", ID_ADXRS453}, + {} +}; +MODULE_DEVICE_TABLE(spi, adxrs450_id); + +static struct spi_driver adxrs450_driver = { + .driver = { + .name = "adxrs450", + .owner = THIS_MODULE, + }, + .probe = adxrs450_probe, + .remove = adxrs450_remove, + .id_table = adxrs450_id, +}; +module_spi_driver(adxrs450_driver); + +MODULE_AUTHOR("Cliff Cai "); +MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/gyro/adxrs450.h b/drivers/staging/iio/gyro/adxrs450.h deleted file mode 100644 index 97abea32f220..000000000000 --- a/drivers/staging/iio/gyro/adxrs450.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef SPI_ADXRS450_H_ -#define SPI_ADXRS450_H_ - -#define ADXRS450_STARTUP_DELAY 50 /* ms */ - -/* The MSB for the spi commands */ -#define ADXRS450_SENSOR_DATA (0x20 << 24) -#define ADXRS450_WRITE_DATA (0x40 << 24) -#define ADXRS450_READ_DATA (0x80 << 24) - -#define ADXRS450_RATE1 0x00 /* Rate Registers */ -#define ADXRS450_TEMP1 0x02 /* Temperature Registers */ -#define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */ -#define ADXRS450_HICST1 0x06 /* High CST Memory Registers */ -#define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */ -#define ADXRS450_FAULT1 0x0A /* Fault Registers */ -#define ADXRS450_PID1 0x0C /* Part ID Register 1 */ -#define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */ -#define ADXRS450_SNL 0x10 -#define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */ -/* Check bits */ -#define ADXRS450_P 0x01 -#define ADXRS450_CHK 0x02 -#define ADXRS450_CST 0x04 -#define ADXRS450_PWR 0x08 -#define ADXRS450_POR 0x10 -#define ADXRS450_NVM 0x20 -#define ADXRS450_Q 0x40 -#define ADXRS450_PLL 0x80 -#define ADXRS450_UV 0x100 -#define ADXRS450_OV 0x200 -#define ADXRS450_AMP 0x400 -#define ADXRS450_FAIL 0x800 - -#define ADXRS450_WRERR_MASK (0x7 << 29) - -#define ADXRS450_MAX_RX 4 -#define ADXRS450_MAX_TX 4 - -#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3) - -enum { - ID_ADXRS450, - ID_ADXRS453, -}; - -/** - * struct adxrs450_state - device instance specific data - * @us: actual spi_device - * @buf_lock: mutex to protect tx and rx - * @tx: transmit buffer - * @rx: receive buffer - **/ -struct adxrs450_state { - struct spi_device *us; - struct mutex buf_lock; - __be32 tx ____cacheline_aligned; - __be32 rx; - -}; - -#endif /* SPI_ADXRS450_H_ */ diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c deleted file mode 100644 index 714e3239d5d6..000000000000 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * ADXRS450/ADXRS453 Digital Output Gyroscope Driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "adxrs450.h" - -/** - * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair - * @indio_dev: device associated with child of actual iio_dev - * @reg_address: the address of the lower of the two registers, which should be - * an even address, the second register's address is reg_address + 1. - * @val: somewhere to pass back the value read - **/ -static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 *val) -{ - struct spi_message msg; - struct adxrs450_state *st = iio_priv(indio_dev); - u32 tx; - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = &st->tx, - .bits_per_word = 8, - .len = sizeof(st->tx), - .cs_change = 1, - }, { - .rx_buf = &st->rx, - .bits_per_word = 8, - .len = sizeof(st->rx), - }, - }; - - mutex_lock(&st->buf_lock); - tx = ADXRS450_READ_DATA | (reg_address << 17); - - if (!(hweight32(tx) & 1)) - tx |= ADXRS450_P; - - st->tx = cpu_to_be32(tx); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", - reg_address); - goto error_ret; - } - - *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair - * @indio_dev: device associated with child of actual actual iio_dev - * @reg_address: the address of the lower of the two registers,which should be - * an even address, the second register's address is reg_address + 1. - * @val: value to be written. - **/ -static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 val) -{ - struct adxrs450_state *st = iio_priv(indio_dev); - u32 tx; - int ret; - - mutex_lock(&st->buf_lock); - tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1); - - if (!(hweight32(tx) & 1)) - tx |= ADXRS450_P; - - st->tx = cpu_to_be32(tx); - ret = spi_write(st->us, &st->tx, sizeof(st->tx)); - if (ret) - dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", - reg_address); - usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */ - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_sensor_data() - read 2 bytes sensor data - * @indio_dev: device associated with child of actual iio_dev - * @val: somewhere to pass back the value read - **/ -static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) -{ - struct spi_message msg; - struct adxrs450_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = &st->tx, - .bits_per_word = 8, - .len = sizeof(st->tx), - .cs_change = 1, - }, { - .rx_buf = &st->rx, - .bits_per_word = 8, - .len = sizeof(st->rx), - }, - }; - - mutex_lock(&st->buf_lock); - st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "Problem while reading sensor data\n"); - goto error_ret; - } - - *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_initial() - use for initializing procedure. - * @st: device instance specific data - * @val: somewhere to pass back the value read - * @chk: Whether to perform fault check - **/ -static int adxrs450_spi_initial(struct adxrs450_state *st, - u32 *val, char chk) -{ - struct spi_message msg; - int ret; - u32 tx; - struct spi_transfer xfers = { - .tx_buf = &st->tx, - .rx_buf = &st->rx, - .bits_per_word = 8, - .len = sizeof(st->tx), - }; - - mutex_lock(&st->buf_lock); - tx = ADXRS450_SENSOR_DATA; - if (chk) - tx |= (ADXRS450_CHK | ADXRS450_P); - st->tx = cpu_to_be32(tx); - spi_message_init(&msg); - spi_message_add_tail(&xfers, &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "Problem while reading initializing data\n"); - goto error_ret; - } - - *val = be32_to_cpu(st->rx); - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/* Recommended Startup Sequence by spec */ -static int adxrs450_initial_setup(struct iio_dev *indio_dev) -{ - u32 t; - u16 data; - int ret; - struct adxrs450_state *st = iio_priv(indio_dev); - - msleep(ADXRS450_STARTUP_DELAY*2); - ret = adxrs450_spi_initial(st, &t, 1); - if (ret) - return ret; - if (t != 0x01) - dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n"); - - msleep(ADXRS450_STARTUP_DELAY); - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - - msleep(ADXRS450_STARTUP_DELAY); - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { - dev_err(&st->us->dev, "The second response is not correct!\n"); - return -EIO; - - } - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { - dev_err(&st->us->dev, "The third response is not correct!\n"); - return -EIO; - - } - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); - if (ret) - return ret; - if (data & 0x0fff) { - dev_err(&st->us->dev, "The device is not in normal status!\n"); - return -EINVAL; - } - - return 0; -} - -static int adxrs450_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - int ret; - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - if (val < -0x400 || val >= 0x400) - return -EINVAL; - ret = adxrs450_spi_write_reg_16(indio_dev, - ADXRS450_DNC1, val); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int adxrs450_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret; - s16 t; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - switch (chan->type) { - case IIO_ANGL_VEL: - ret = adxrs450_spi_sensor_data(indio_dev, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - case IIO_TEMP: - ret = adxrs450_spi_read_reg_16(indio_dev, - ADXRS450_TEMP1, &t); - if (ret) - break; - *val = (t >> 6) + 225; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - break; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ANGL_VEL: - *val = 0; - *val2 = 218166; - return IIO_VAL_INT_PLUS_NANO; - case IIO_TEMP: - *val = 200; - *val2 = 0; - return IIO_VAL_INT; - default: - return -EINVAL; - } - break; - case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_CALIBBIAS: - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); - if (ret) - break; - *val = sign_extend32(t, 9); - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct iio_chan_spec adxrs450_channels[2][2] = { - [ID_ADXRS450] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - } - }, - [ID_ADXRS453] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - } - }, -}; - -static const struct iio_info adxrs450_info = { - .driver_module = THIS_MODULE, - .read_raw = &adxrs450_read_raw, - .write_raw = &adxrs450_write_raw, -}; - -static int adxrs450_probe(struct spi_device *spi) -{ - int ret; - struct adxrs450_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = iio_device_alloc(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - /* This is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adxrs450_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = - adxrs450_channels[spi_get_device_id(spi)->driver_data]; - indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); - indio_dev->name = spi->dev.driver->name; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - /* Get the device into a sane initial state */ - ret = adxrs450_initial_setup(indio_dev); - if (ret) - goto error_initial; - return 0; -error_initial: - iio_device_unregister(indio_dev); -error_free_dev: - iio_device_free(indio_dev); - -error_ret: - return ret; -} - -static int adxrs450_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_device_free(spi_get_drvdata(spi)); - - return 0; -} - -static const struct spi_device_id adxrs450_id[] = { - {"adxrs450", ID_ADXRS450}, - {"adxrs453", ID_ADXRS453}, - {} -}; -MODULE_DEVICE_TABLE(spi, adxrs450_id); - -static struct spi_driver adxrs450_driver = { - .driver = { - .name = "adxrs450", - .owner = THIS_MODULE, - }, - .probe = adxrs450_probe, - .remove = adxrs450_remove, - .id_table = adxrs450_id, -}; -module_spi_driver(adxrs450_driver); - -MODULE_AUTHOR("Cliff Cai "); -MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 420b0fcb523b61eefb347317d3956db3249e968d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 31 Jan 2013 14:27:00 +0000 Subject: staging:iio: Move adxrs450 driver out of staging The adxrs450 is in a reasonable shape now. It follows the IIO ABI and non of the standard code checker tools report any issue, so move it out of staging. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/Kconfig | 10 + drivers/iio/gyro/Makefile | 2 + drivers/iio/gyro/adxrs450.c | 497 ++++++++++++++++++++++++++++++++++++ drivers/staging/iio/gyro/Kconfig | 10 - drivers/staging/iio/gyro/Makefile | 2 - drivers/staging/iio/gyro/adxrs450.c | 497 ------------------------------------ 6 files changed, 509 insertions(+), 509 deletions(-) create mode 100644 drivers/iio/gyro/adxrs450.c delete mode 100644 drivers/staging/iio/gyro/adxrs450.c (limited to 'drivers/staging/iio/gyro') diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index c9f177dd4cc7..51ac6bc791c6 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -19,6 +19,16 @@ config ADIS16136 Say yes here to build support for the Analog Devices ADIS16133, ADIS16135, ADIS16136 gyroscope devices. +config ADXRS450 + tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices ADXRS450 and ADXRS453 + programmable digital output gyroscope. + + This driver can also be built as a module. If so, the module + will be called adxrs450. + config HID_SENSOR_GYRO_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index 66b517d9468a..eff9bb0119a2 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_ADIS16080) += adis16080.o obj-$(CONFIG_ADIS16136) += adis16136.o +obj-$(CONFIG_ADXRS450) += adxrs450.o + obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o obj-$(CONFIG_IIO_ST_GYRO_3AXIS) += st_gyro.o diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c new file mode 100644 index 000000000000..d9d43831c380 --- /dev/null +++ b/drivers/iio/gyro/adxrs450.c @@ -0,0 +1,497 @@ +/* + * ADXRS450/ADXRS453 Digital Output Gyroscope Driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define ADXRS450_STARTUP_DELAY 50 /* ms */ + +/* The MSB for the spi commands */ +#define ADXRS450_SENSOR_DATA (0x20 << 24) +#define ADXRS450_WRITE_DATA (0x40 << 24) +#define ADXRS450_READ_DATA (0x80 << 24) + +#define ADXRS450_RATE1 0x00 /* Rate Registers */ +#define ADXRS450_TEMP1 0x02 /* Temperature Registers */ +#define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */ +#define ADXRS450_HICST1 0x06 /* High CST Memory Registers */ +#define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */ +#define ADXRS450_FAULT1 0x0A /* Fault Registers */ +#define ADXRS450_PID1 0x0C /* Part ID Register 1 */ +#define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */ +#define ADXRS450_SNL 0x10 +#define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */ +/* Check bits */ +#define ADXRS450_P 0x01 +#define ADXRS450_CHK 0x02 +#define ADXRS450_CST 0x04 +#define ADXRS450_PWR 0x08 +#define ADXRS450_POR 0x10 +#define ADXRS450_NVM 0x20 +#define ADXRS450_Q 0x40 +#define ADXRS450_PLL 0x80 +#define ADXRS450_UV 0x100 +#define ADXRS450_OV 0x200 +#define ADXRS450_AMP 0x400 +#define ADXRS450_FAIL 0x800 + +#define ADXRS450_WRERR_MASK (0x7 << 29) + +#define ADXRS450_MAX_RX 4 +#define ADXRS450_MAX_TX 4 + +#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3) + +enum { + ID_ADXRS450, + ID_ADXRS453, +}; + +/** + * struct adxrs450_state - device instance specific data + * @us: actual spi_device + * @buf_lock: mutex to protect tx and rx + * @tx: transmit buffer + * @rx: receive buffer + **/ +struct adxrs450_state { + struct spi_device *us; + struct mutex buf_lock; + __be32 tx ____cacheline_aligned; + __be32 rx; + +}; + +/** + * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair + * @indio_dev: device associated with child of actual iio_dev + * @reg_address: the address of the lower of the two registers, which should be + * an even address, the second register's address is reg_address + 1. + * @val: somewhere to pass back the value read + **/ +static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, + u8 reg_address, + u16 *val) +{ + struct spi_message msg; + struct adxrs450_state *st = iio_priv(indio_dev); + u32 tx; + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = &st->tx, + .bits_per_word = 8, + .len = sizeof(st->tx), + .cs_change = 1, + }, { + .rx_buf = &st->rx, + .bits_per_word = 8, + .len = sizeof(st->rx), + }, + }; + + mutex_lock(&st->buf_lock); + tx = ADXRS450_READ_DATA | (reg_address << 17); + + if (!(hweight32(tx) & 1)) + tx |= ADXRS450_P; + + st->tx = cpu_to_be32(tx); + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", + reg_address); + goto error_ret; + } + + *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair + * @indio_dev: device associated with child of actual actual iio_dev + * @reg_address: the address of the lower of the two registers,which should be + * an even address, the second register's address is reg_address + 1. + * @val: value to be written. + **/ +static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, + u8 reg_address, + u16 val) +{ + struct adxrs450_state *st = iio_priv(indio_dev); + u32 tx; + int ret; + + mutex_lock(&st->buf_lock); + tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1); + + if (!(hweight32(tx) & 1)) + tx |= ADXRS450_P; + + st->tx = cpu_to_be32(tx); + ret = spi_write(st->us, &st->tx, sizeof(st->tx)); + if (ret) + dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", + reg_address); + usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */ + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adxrs450_spi_sensor_data() - read 2 bytes sensor data + * @indio_dev: device associated with child of actual iio_dev + * @val: somewhere to pass back the value read + **/ +static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) +{ + struct spi_message msg; + struct adxrs450_state *st = iio_priv(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = &st->tx, + .bits_per_word = 8, + .len = sizeof(st->tx), + .cs_change = 1, + }, { + .rx_buf = &st->rx, + .bits_per_word = 8, + .len = sizeof(st->rx), + }, + }; + + mutex_lock(&st->buf_lock); + st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "Problem while reading sensor data\n"); + goto error_ret; + } + + *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adxrs450_spi_initial() - use for initializing procedure. + * @st: device instance specific data + * @val: somewhere to pass back the value read + * @chk: Whether to perform fault check + **/ +static int adxrs450_spi_initial(struct adxrs450_state *st, + u32 *val, char chk) +{ + struct spi_message msg; + int ret; + u32 tx; + struct spi_transfer xfers = { + .tx_buf = &st->tx, + .rx_buf = &st->rx, + .bits_per_word = 8, + .len = sizeof(st->tx), + }; + + mutex_lock(&st->buf_lock); + tx = ADXRS450_SENSOR_DATA; + if (chk) + tx |= (ADXRS450_CHK | ADXRS450_P); + st->tx = cpu_to_be32(tx); + spi_message_init(&msg); + spi_message_add_tail(&xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "Problem while reading initializing data\n"); + goto error_ret; + } + + *val = be32_to_cpu(st->rx); + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +/* Recommended Startup Sequence by spec */ +static int adxrs450_initial_setup(struct iio_dev *indio_dev) +{ + u32 t; + u16 data; + int ret; + struct adxrs450_state *st = iio_priv(indio_dev); + + msleep(ADXRS450_STARTUP_DELAY*2); + ret = adxrs450_spi_initial(st, &t, 1); + if (ret) + return ret; + if (t != 0x01) + dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n"); + + msleep(ADXRS450_STARTUP_DELAY); + ret = adxrs450_spi_initial(st, &t, 0); + if (ret) + return ret; + + msleep(ADXRS450_STARTUP_DELAY); + ret = adxrs450_spi_initial(st, &t, 0); + if (ret) + return ret; + if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { + dev_err(&st->us->dev, "The second response is not correct!\n"); + return -EIO; + + } + ret = adxrs450_spi_initial(st, &t, 0); + if (ret) + return ret; + if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { + dev_err(&st->us->dev, "The third response is not correct!\n"); + return -EIO; + + } + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); + if (ret) + return ret; + if (data & 0x0fff) { + dev_err(&st->us->dev, "The device is not in normal status!\n"); + return -EINVAL; + } + + return 0; +} + +static int adxrs450_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int ret; + switch (mask) { + case IIO_CHAN_INFO_CALIBBIAS: + if (val < -0x400 || val >= 0x400) + return -EINVAL; + ret = adxrs450_spi_write_reg_16(indio_dev, + ADXRS450_DNC1, val); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int adxrs450_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + s16 t; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ANGL_VEL: + ret = adxrs450_spi_sensor_data(indio_dev, &t); + if (ret) + break; + *val = t; + ret = IIO_VAL_INT; + break; + case IIO_TEMP: + ret = adxrs450_spi_read_reg_16(indio_dev, + ADXRS450_TEMP1, &t); + if (ret) + break; + *val = (t >> 6) + 225; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + break; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = 0; + *val2 = 218166; + return IIO_VAL_INT_PLUS_NANO; + case IIO_TEMP: + *val = 200; + *val2 = 0; + return IIO_VAL_INT; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); + if (ret) + break; + *val = t; + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_CALIBBIAS: + ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); + if (ret) + break; + *val = sign_extend32(t, 9); + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const struct iio_chan_spec adxrs450_channels[2][2] = { + [ID_ADXRS450] = { + { + .type = IIO_ANGL_VEL, + .modified = 1, + .channel2 = IIO_MOD_Z, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + } + }, + [ID_ADXRS453] = { + { + .type = IIO_ANGL_VEL, + .modified = 1, + .channel2 = IIO_MOD_Z, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT, + }, { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + } + }, +}; + +static const struct iio_info adxrs450_info = { + .driver_module = THIS_MODULE, + .read_raw = &adxrs450_read_raw, + .write_raw = &adxrs450_write_raw, +}; + +static int adxrs450_probe(struct spi_device *spi) +{ + int ret; + struct adxrs450_state *st; + struct iio_dev *indio_dev; + + /* setup the industrialio driver allocated elements */ + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + st = iio_priv(indio_dev); + st->us = spi; + mutex_init(&st->buf_lock); + /* This is only used for removal purposes */ + spi_set_drvdata(spi, indio_dev); + + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &adxrs450_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = + adxrs450_channels[spi_get_device_id(spi)->driver_data]; + indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); + indio_dev->name = spi->dev.driver->name; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_dev; + + /* Get the device into a sane initial state */ + ret = adxrs450_initial_setup(indio_dev); + if (ret) + goto error_initial; + return 0; +error_initial: + iio_device_unregister(indio_dev); +error_free_dev: + iio_device_free(indio_dev); + +error_ret: + return ret; +} + +static int adxrs450_remove(struct spi_device *spi) +{ + iio_device_unregister(spi_get_drvdata(spi)); + iio_device_free(spi_get_drvdata(spi)); + + return 0; +} + +static const struct spi_device_id adxrs450_id[] = { + {"adxrs450", ID_ADXRS450}, + {"adxrs453", ID_ADXRS453}, + {} +}; +MODULE_DEVICE_TABLE(spi, adxrs450_id); + +static struct spi_driver adxrs450_driver = { + .driver = { + .name = "adxrs450", + .owner = THIS_MODULE, + }, + .probe = adxrs450_probe, + .remove = adxrs450_remove, + .id_table = adxrs450_id, +}; +module_spi_driver(adxrs450_driver); + +MODULE_AUTHOR("Cliff Cai "); +MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig index 658b3673d056..836066287192 100644 --- a/drivers/staging/iio/gyro/Kconfig +++ b/drivers/staging/iio/gyro/Kconfig @@ -29,14 +29,4 @@ config ADIS16260 This driver can also be built as a module. If so, the module will be called adis16260. -config ADXRS450 - tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver" - depends on SPI - help - Say yes here to build support for Analog Devices ADXRS450 and ADXRS453 - programmable digital output gyroscope. - - This driver can also be built as a module. If so, the module - will be called adxrs450. - endmenu diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile index 6b4e60ab743f..98e650061a3a 100644 --- a/drivers/staging/iio/gyro/Makefile +++ b/drivers/staging/iio/gyro/Makefile @@ -10,5 +10,3 @@ obj-$(CONFIG_ADIS16130) += adis16130.o adis16260-y := adis16260_core.o obj-$(CONFIG_ADIS16260) += adis16260.o - -obj-$(CONFIG_ADXRS450) += adxrs450.o diff --git a/drivers/staging/iio/gyro/adxrs450.c b/drivers/staging/iio/gyro/adxrs450.c deleted file mode 100644 index d9d43831c380..000000000000 --- a/drivers/staging/iio/gyro/adxrs450.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * ADXRS450/ADXRS453 Digital Output Gyroscope Driver - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define ADXRS450_STARTUP_DELAY 50 /* ms */ - -/* The MSB for the spi commands */ -#define ADXRS450_SENSOR_DATA (0x20 << 24) -#define ADXRS450_WRITE_DATA (0x40 << 24) -#define ADXRS450_READ_DATA (0x80 << 24) - -#define ADXRS450_RATE1 0x00 /* Rate Registers */ -#define ADXRS450_TEMP1 0x02 /* Temperature Registers */ -#define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */ -#define ADXRS450_HICST1 0x06 /* High CST Memory Registers */ -#define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */ -#define ADXRS450_FAULT1 0x0A /* Fault Registers */ -#define ADXRS450_PID1 0x0C /* Part ID Register 1 */ -#define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */ -#define ADXRS450_SNL 0x10 -#define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */ -/* Check bits */ -#define ADXRS450_P 0x01 -#define ADXRS450_CHK 0x02 -#define ADXRS450_CST 0x04 -#define ADXRS450_PWR 0x08 -#define ADXRS450_POR 0x10 -#define ADXRS450_NVM 0x20 -#define ADXRS450_Q 0x40 -#define ADXRS450_PLL 0x80 -#define ADXRS450_UV 0x100 -#define ADXRS450_OV 0x200 -#define ADXRS450_AMP 0x400 -#define ADXRS450_FAIL 0x800 - -#define ADXRS450_WRERR_MASK (0x7 << 29) - -#define ADXRS450_MAX_RX 4 -#define ADXRS450_MAX_TX 4 - -#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3) - -enum { - ID_ADXRS450, - ID_ADXRS453, -}; - -/** - * struct adxrs450_state - device instance specific data - * @us: actual spi_device - * @buf_lock: mutex to protect tx and rx - * @tx: transmit buffer - * @rx: receive buffer - **/ -struct adxrs450_state { - struct spi_device *us; - struct mutex buf_lock; - __be32 tx ____cacheline_aligned; - __be32 rx; - -}; - -/** - * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair - * @indio_dev: device associated with child of actual iio_dev - * @reg_address: the address of the lower of the two registers, which should be - * an even address, the second register's address is reg_address + 1. - * @val: somewhere to pass back the value read - **/ -static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 *val) -{ - struct spi_message msg; - struct adxrs450_state *st = iio_priv(indio_dev); - u32 tx; - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = &st->tx, - .bits_per_word = 8, - .len = sizeof(st->tx), - .cs_change = 1, - }, { - .rx_buf = &st->rx, - .bits_per_word = 8, - .len = sizeof(st->rx), - }, - }; - - mutex_lock(&st->buf_lock); - tx = ADXRS450_READ_DATA | (reg_address << 17); - - if (!(hweight32(tx) & 1)) - tx |= ADXRS450_P; - - st->tx = cpu_to_be32(tx); - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", - reg_address); - goto error_ret; - } - - *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair - * @indio_dev: device associated with child of actual actual iio_dev - * @reg_address: the address of the lower of the two registers,which should be - * an even address, the second register's address is reg_address + 1. - * @val: value to be written. - **/ -static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, - u8 reg_address, - u16 val) -{ - struct adxrs450_state *st = iio_priv(indio_dev); - u32 tx; - int ret; - - mutex_lock(&st->buf_lock); - tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1); - - if (!(hweight32(tx) & 1)) - tx |= ADXRS450_P; - - st->tx = cpu_to_be32(tx); - ret = spi_write(st->us, &st->tx, sizeof(st->tx)); - if (ret) - dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", - reg_address); - usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */ - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_sensor_data() - read 2 bytes sensor data - * @indio_dev: device associated with child of actual iio_dev - * @val: somewhere to pass back the value read - **/ -static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) -{ - struct spi_message msg; - struct adxrs450_state *st = iio_priv(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = &st->tx, - .bits_per_word = 8, - .len = sizeof(st->tx), - .cs_change = 1, - }, { - .rx_buf = &st->rx, - .bits_per_word = 8, - .len = sizeof(st->rx), - }, - }; - - mutex_lock(&st->buf_lock); - st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "Problem while reading sensor data\n"); - goto error_ret; - } - - *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF; - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/** - * adxrs450_spi_initial() - use for initializing procedure. - * @st: device instance specific data - * @val: somewhere to pass back the value read - * @chk: Whether to perform fault check - **/ -static int adxrs450_spi_initial(struct adxrs450_state *st, - u32 *val, char chk) -{ - struct spi_message msg; - int ret; - u32 tx; - struct spi_transfer xfers = { - .tx_buf = &st->tx, - .rx_buf = &st->rx, - .bits_per_word = 8, - .len = sizeof(st->tx), - }; - - mutex_lock(&st->buf_lock); - tx = ADXRS450_SENSOR_DATA; - if (chk) - tx |= (ADXRS450_CHK | ADXRS450_P); - st->tx = cpu_to_be32(tx); - spi_message_init(&msg); - spi_message_add_tail(&xfers, &msg); - ret = spi_sync(st->us, &msg); - if (ret) { - dev_err(&st->us->dev, "Problem while reading initializing data\n"); - goto error_ret; - } - - *val = be32_to_cpu(st->rx); - -error_ret: - mutex_unlock(&st->buf_lock); - return ret; -} - -/* Recommended Startup Sequence by spec */ -static int adxrs450_initial_setup(struct iio_dev *indio_dev) -{ - u32 t; - u16 data; - int ret; - struct adxrs450_state *st = iio_priv(indio_dev); - - msleep(ADXRS450_STARTUP_DELAY*2); - ret = adxrs450_spi_initial(st, &t, 1); - if (ret) - return ret; - if (t != 0x01) - dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n"); - - msleep(ADXRS450_STARTUP_DELAY); - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - - msleep(ADXRS450_STARTUP_DELAY); - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { - dev_err(&st->us->dev, "The second response is not correct!\n"); - return -EIO; - - } - ret = adxrs450_spi_initial(st, &t, 0); - if (ret) - return ret; - if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { - dev_err(&st->us->dev, "The third response is not correct!\n"); - return -EIO; - - } - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); - if (ret) - return ret; - if (data & 0x0fff) { - dev_err(&st->us->dev, "The device is not in normal status!\n"); - return -EINVAL; - } - - return 0; -} - -static int adxrs450_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - int ret; - switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS: - if (val < -0x400 || val >= 0x400) - return -EINVAL; - ret = adxrs450_spi_write_reg_16(indio_dev, - ADXRS450_DNC1, val); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int adxrs450_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long mask) -{ - int ret; - s16 t; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - switch (chan->type) { - case IIO_ANGL_VEL: - ret = adxrs450_spi_sensor_data(indio_dev, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - case IIO_TEMP: - ret = adxrs450_spi_read_reg_16(indio_dev, - ADXRS450_TEMP1, &t); - if (ret) - break; - *val = (t >> 6) + 225; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - break; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ANGL_VEL: - *val = 0; - *val2 = 218166; - return IIO_VAL_INT_PLUS_NANO; - case IIO_TEMP: - *val = 200; - *val2 = 0; - return IIO_VAL_INT; - default: - return -EINVAL; - } - break; - case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); - if (ret) - break; - *val = t; - ret = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_CALIBBIAS: - ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); - if (ret) - break; - *val = sign_extend32(t, 9); - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct iio_chan_spec adxrs450_channels[2][2] = { - [ID_ADXRS450] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - } - }, - [ID_ADXRS453] = { - { - .type = IIO_ANGL_VEL, - .modified = 1, - .channel2 = IIO_MOD_Z, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT | - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT, - }, { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, - } - }, -}; - -static const struct iio_info adxrs450_info = { - .driver_module = THIS_MODULE, - .read_raw = &adxrs450_read_raw, - .write_raw = &adxrs450_write_raw, -}; - -static int adxrs450_probe(struct spi_device *spi) -{ - int ret; - struct adxrs450_state *st; - struct iio_dev *indio_dev; - - /* setup the industrialio driver allocated elements */ - indio_dev = iio_device_alloc(sizeof(*st)); - if (indio_dev == NULL) { - ret = -ENOMEM; - goto error_ret; - } - st = iio_priv(indio_dev); - st->us = spi; - mutex_init(&st->buf_lock); - /* This is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); - - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &adxrs450_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = - adxrs450_channels[spi_get_device_id(spi)->driver_data]; - indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); - indio_dev->name = spi->dev.driver->name; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_dev; - - /* Get the device into a sane initial state */ - ret = adxrs450_initial_setup(indio_dev); - if (ret) - goto error_initial; - return 0; -error_initial: - iio_device_unregister(indio_dev); -error_free_dev: - iio_device_free(indio_dev); - -error_ret: - return ret; -} - -static int adxrs450_remove(struct spi_device *spi) -{ - iio_device_unregister(spi_get_drvdata(spi)); - iio_device_free(spi_get_drvdata(spi)); - - return 0; -} - -static const struct spi_device_id adxrs450_id[] = { - {"adxrs450", ID_ADXRS450}, - {"adxrs453", ID_ADXRS453}, - {} -}; -MODULE_DEVICE_TABLE(spi, adxrs450_id); - -static struct spi_driver adxrs450_driver = { - .driver = { - .name = "adxrs450", - .owner = THIS_MODULE, - }, - .probe = adxrs450_probe, - .remove = adxrs450_remove, - .id_table = adxrs450_id, -}; -module_spi_driver(adxrs450_driver); - -MODULE_AUTHOR("Cliff Cai "); -MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3