diff options
author | Irina Tirdea <irina.tirdea@intel.com> | 2015-01-29 21:45:10 +0300 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2015-01-30 23:34:59 +0300 |
commit | 40cb761306d6c19d80fe85f9ae52615932f76b71 (patch) | |
tree | 238c05112d8485c90dc227dae7c87d02efaffc95 /drivers/iio/accel/mma9551_core.c | |
parent | 81110933a94279afce73beecae568e704cf2b9b6 (diff) | |
download | linux-40cb761306d6c19d80fe85f9ae52615932f76b71.tar.xz |
iio: add driver for Freescale MMA9553
Add support for Freescale MMA9553L Intelligent Pedometer Platform.
The following functionalities are supported:
- step counter (counts the number of steps using a HW register)
- step detector (generates an iio event at every step the user takes)
- activity recognition (rest, walking, jogging, running)
- speed
- calories
- distance
To get accurate pedometer results, the user's height, weight and gender
need to be configured.
The specifications can be downloaded from:
http://www.freescale.com/files/sensors/doc/ref_manual/MMA955xLSWRM.pdf
http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf
Signed-off-by: Irina Tirdea <irina.tirdea@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/accel/mma9551_core.c')
-rw-r--r-- | drivers/iio/accel/mma9551_core.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c index 7f1a73e6aa36..7f55a6d7cd03 100644 --- a/drivers/iio/accel/mma9551_core.c +++ b/drivers/iio/accel/mma9551_core.c @@ -53,6 +53,11 @@ #define MMA9551_AFE_Y_ACCEL_REG 0x02 #define MMA9551_AFE_Z_ACCEL_REG 0x04 +/* Reset/Suspend/Clear application */ +#define MMA9551_RSC_RESET 0x00 +#define MMA9551_RSC_OFFSET(mask) (3 - (ffs(mask) - 1) / 8) +#define MMA9551_RSC_VAL(mask) (mask >> (((ffs(mask) - 1) / 8) * 8)) + /* * A response is composed of: * - control registers: MB0-3 @@ -275,6 +280,64 @@ int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, EXPORT_SYMBOL(mma9551_read_status_byte); /** + * mma9551_read_config_word() - read 1 config word + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Pointer to store value read + * + * Read one configuration word from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed by one or + * more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_config_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 *val) +{ + int ret; + __be16 v; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, + reg, NULL, 0, (u8 *)&v, 2); + *val = be16_to_cpu(v); + + return ret; +} +EXPORT_SYMBOL(mma9551_read_config_word); + +/** + * mma9551_write_config_word() - write 1 config word + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Value to write + * + * Write one configuration word from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed by one or + * more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_write_config_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 val) +{ + __be16 v = cpu_to_be16(val); + + return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, + (u8 *) &v, 2, NULL, 0); +} +EXPORT_SYMBOL(mma9551_write_config_word); + +/** * mma9551_read_status_word() - read 1 status word * @client: I2C client * @app_id: Application ID @@ -306,6 +369,107 @@ int mma9551_read_status_word(struct i2c_client *client, u8 app_id, EXPORT_SYMBOL(mma9551_read_status_word); /** + * mma9551_read_config_words() - read multiple config words + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @len: Length of array to read in bytes + * @val: Array of words to read + * + * Read multiple configuration registers (word-sized registers). + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_config_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf) +{ + int ret, i; + int len_words = len / sizeof(u16); + __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS]; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, + reg, NULL, 0, (u8 *) be_buf, len); + if (ret < 0) + return ret; + + for (i = 0; i < len_words; i++) + buf[i] = be16_to_cpu(be_buf[i]); + + return 0; +} +EXPORT_SYMBOL(mma9551_read_config_words); + +/** + * mma9551_read_status_words() - read multiple status words + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @len: Length of array to read in bytes + * @val: Array of words to read + * + * Read multiple status registers (word-sized registers). + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_status_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf) +{ + int ret, i; + int len_words = len / sizeof(u16); + __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS]; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, (u8 *) be_buf, len); + if (ret < 0) + return ret; + + for (i = 0; i < len_words; i++) + buf[i] = be16_to_cpu(be_buf[i]); + + return 0; +} +EXPORT_SYMBOL(mma9551_read_status_words); + +/** + * mma9551_write_config_words() - write multiple config words + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @len: Length of array to write in bytes + * @val: Array of words to write + * + * Write multiple configuration registers (word-sized registers). + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_write_config_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf) +{ + int i; + int len_words = len / sizeof(u16); + __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS]; + + for (i = 0; i < len_words; i++) + be_buf[i] = cpu_to_be16(buf[i]); + + return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, + reg, (u8 *) be_buf, len, NULL, 0); +} +EXPORT_SYMBOL(mma9551_write_config_words); + +/** * mma9551_update_config_bits() - update bits in register * @client: I2C client * @app_id: Application ID @@ -609,6 +773,25 @@ int mma9551_read_accel_scale(int *val, int *val2) } EXPORT_SYMBOL(mma9551_read_accel_scale); +/** + * mma9551_app_reset() - reset application + * @client: I2C client + * @app_mask: Application to reset + * + * Reset the given application (using the Reset/Suspend/Clear + * Control Application) + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_app_reset(struct i2c_client *client, u32 app_mask) +{ + return mma9551_write_config_byte(client, MMA9551_APPID_RCS, + MMA9551_RSC_RESET + + MMA9551_RSC_OFFSET(app_mask), + MMA9551_RSC_VAL(app_mask)); +} +EXPORT_SYMBOL(mma9551_app_reset); + MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>"); MODULE_LICENSE("GPL v2"); |