132133be6SConstantin Musca /** 232133be6SConstantin Musca * Freescale MMA7660FC 3-Axis Accelerometer 332133be6SConstantin Musca * 432133be6SConstantin Musca * Copyright (c) 2016, Intel Corporation. 532133be6SConstantin Musca * 632133be6SConstantin Musca * This file is subject to the terms and conditions of version 2 of 732133be6SConstantin Musca * the GNU General Public License. See the file COPYING in the main 832133be6SConstantin Musca * directory of this archive for more details. 932133be6SConstantin Musca * 1032133be6SConstantin Musca * IIO driver for Freescale MMA7660FC; 7-bit I2C address: 0x4c. 1132133be6SConstantin Musca */ 1232133be6SConstantin Musca 1332133be6SConstantin Musca #include <linux/acpi.h> 1432133be6SConstantin Musca #include <linux/i2c.h> 1532133be6SConstantin Musca #include <linux/module.h> 1632133be6SConstantin Musca #include <linux/iio/iio.h> 1732133be6SConstantin Musca #include <linux/iio/sysfs.h> 1832133be6SConstantin Musca 1932133be6SConstantin Musca #define MMA7660_DRIVER_NAME "mma7660" 2032133be6SConstantin Musca 2132133be6SConstantin Musca #define MMA7660_REG_XOUT 0x00 2232133be6SConstantin Musca #define MMA7660_REG_YOUT 0x01 2332133be6SConstantin Musca #define MMA7660_REG_ZOUT 0x02 2432133be6SConstantin Musca #define MMA7660_REG_OUT_BIT_ALERT BIT(6) 2532133be6SConstantin Musca 2632133be6SConstantin Musca #define MMA7660_REG_MODE 0x07 2732133be6SConstantin Musca #define MMA7660_REG_MODE_BIT_MODE BIT(0) 2832133be6SConstantin Musca #define MMA7660_REG_MODE_BIT_TON BIT(2) 2932133be6SConstantin Musca 3032133be6SConstantin Musca #define MMA7660_I2C_READ_RETRIES 5 3132133be6SConstantin Musca 3232133be6SConstantin Musca /* 3332133be6SConstantin Musca * The accelerometer has one measurement range: 3432133be6SConstantin Musca * 3532133be6SConstantin Musca * -1.5g - +1.5g (6-bit, signed) 3632133be6SConstantin Musca * 3732133be6SConstantin Musca * scale = (1.5 + 1.5) * 9.81 / (2^6 - 1) = 0.467142857 3832133be6SConstantin Musca */ 3932133be6SConstantin Musca 4032133be6SConstantin Musca #define MMA7660_SCALE_AVAIL "0.467142857" 4132133be6SConstantin Musca 4232133be6SConstantin Musca const int mma7660_nscale = 467142857; 4332133be6SConstantin Musca 4432133be6SConstantin Musca #define MMA7660_CHANNEL(reg, axis) { \ 4532133be6SConstantin Musca .type = IIO_ACCEL, \ 4632133be6SConstantin Musca .address = reg, \ 4732133be6SConstantin Musca .modified = 1, \ 4832133be6SConstantin Musca .channel2 = IIO_MOD_##axis, \ 4932133be6SConstantin Musca .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 5032133be6SConstantin Musca .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 5132133be6SConstantin Musca } 5232133be6SConstantin Musca 5332133be6SConstantin Musca static const struct iio_chan_spec mma7660_channels[] = { 5432133be6SConstantin Musca MMA7660_CHANNEL(MMA7660_REG_XOUT, X), 5532133be6SConstantin Musca MMA7660_CHANNEL(MMA7660_REG_YOUT, Y), 5632133be6SConstantin Musca MMA7660_CHANNEL(MMA7660_REG_ZOUT, Z), 5732133be6SConstantin Musca }; 5832133be6SConstantin Musca 5932133be6SConstantin Musca enum mma7660_mode { 6032133be6SConstantin Musca MMA7660_MODE_STANDBY, 6132133be6SConstantin Musca MMA7660_MODE_ACTIVE 6232133be6SConstantin Musca }; 6332133be6SConstantin Musca 6432133be6SConstantin Musca struct mma7660_data { 6532133be6SConstantin Musca struct i2c_client *client; 6632133be6SConstantin Musca struct mutex lock; 6732133be6SConstantin Musca enum mma7660_mode mode; 6832133be6SConstantin Musca }; 6932133be6SConstantin Musca 7032133be6SConstantin Musca static IIO_CONST_ATTR(in_accel_scale_available, MMA7660_SCALE_AVAIL); 7132133be6SConstantin Musca 7232133be6SConstantin Musca static struct attribute *mma7660_attributes[] = { 7332133be6SConstantin Musca &iio_const_attr_in_accel_scale_available.dev_attr.attr, 7432133be6SConstantin Musca NULL, 7532133be6SConstantin Musca }; 7632133be6SConstantin Musca 7732133be6SConstantin Musca static const struct attribute_group mma7660_attribute_group = { 7832133be6SConstantin Musca .attrs = mma7660_attributes 7932133be6SConstantin Musca }; 8032133be6SConstantin Musca 8132133be6SConstantin Musca static int mma7660_set_mode(struct mma7660_data *data, 8232133be6SConstantin Musca enum mma7660_mode mode) 8332133be6SConstantin Musca { 8432133be6SConstantin Musca int ret; 8532133be6SConstantin Musca struct i2c_client *client = data->client; 8632133be6SConstantin Musca 8732133be6SConstantin Musca if (mode == data->mode) 8832133be6SConstantin Musca return 0; 8932133be6SConstantin Musca 9032133be6SConstantin Musca ret = i2c_smbus_read_byte_data(client, MMA7660_REG_MODE); 9132133be6SConstantin Musca if (ret < 0) { 9232133be6SConstantin Musca dev_err(&client->dev, "failed to read sensor mode\n"); 9332133be6SConstantin Musca return ret; 9432133be6SConstantin Musca } 9532133be6SConstantin Musca 9632133be6SConstantin Musca if (mode == MMA7660_MODE_ACTIVE) { 9732133be6SConstantin Musca ret &= ~MMA7660_REG_MODE_BIT_TON; 9832133be6SConstantin Musca ret |= MMA7660_REG_MODE_BIT_MODE; 9932133be6SConstantin Musca } else { 10032133be6SConstantin Musca ret &= ~MMA7660_REG_MODE_BIT_TON; 10132133be6SConstantin Musca ret &= ~MMA7660_REG_MODE_BIT_MODE; 10232133be6SConstantin Musca } 10332133be6SConstantin Musca 10432133be6SConstantin Musca ret = i2c_smbus_write_byte_data(client, MMA7660_REG_MODE, ret); 10532133be6SConstantin Musca if (ret < 0) { 10632133be6SConstantin Musca dev_err(&client->dev, "failed to change sensor mode\n"); 10732133be6SConstantin Musca return ret; 10832133be6SConstantin Musca } 10932133be6SConstantin Musca 11032133be6SConstantin Musca data->mode = mode; 11132133be6SConstantin Musca 11232133be6SConstantin Musca return ret; 11332133be6SConstantin Musca } 11432133be6SConstantin Musca 11532133be6SConstantin Musca static int mma7660_read_accel(struct mma7660_data *data, u8 address) 11632133be6SConstantin Musca { 11732133be6SConstantin Musca int ret, retries = MMA7660_I2C_READ_RETRIES; 11832133be6SConstantin Musca struct i2c_client *client = data->client; 11932133be6SConstantin Musca 12032133be6SConstantin Musca /* 12132133be6SConstantin Musca * Read data. If the Alert bit is set, the register was read at 12232133be6SConstantin Musca * the same time as the device was attempting to update the content. 12332133be6SConstantin Musca * The solution is to read the register again. Do this only 12432133be6SConstantin Musca * MMA7660_I2C_READ_RETRIES times to avoid spending too much time 12532133be6SConstantin Musca * in the kernel. 12632133be6SConstantin Musca */ 12732133be6SConstantin Musca do { 12832133be6SConstantin Musca ret = i2c_smbus_read_byte_data(client, address); 12932133be6SConstantin Musca if (ret < 0) { 13032133be6SConstantin Musca dev_err(&client->dev, "register read failed\n"); 13132133be6SConstantin Musca return ret; 13232133be6SConstantin Musca } 13332133be6SConstantin Musca } while (retries-- > 0 && ret & MMA7660_REG_OUT_BIT_ALERT); 13432133be6SConstantin Musca 13532133be6SConstantin Musca if (ret & MMA7660_REG_OUT_BIT_ALERT) { 13632133be6SConstantin Musca dev_err(&client->dev, "all register read retries failed\n"); 13732133be6SConstantin Musca return -ETIMEDOUT; 13832133be6SConstantin Musca } 13932133be6SConstantin Musca 14032133be6SConstantin Musca return ret; 14132133be6SConstantin Musca } 14232133be6SConstantin Musca 14332133be6SConstantin Musca static int mma7660_read_raw(struct iio_dev *indio_dev, 14432133be6SConstantin Musca struct iio_chan_spec const *chan, 14532133be6SConstantin Musca int *val, int *val2, long mask) 14632133be6SConstantin Musca { 14732133be6SConstantin Musca struct mma7660_data *data = iio_priv(indio_dev); 14832133be6SConstantin Musca int ret; 14932133be6SConstantin Musca 15032133be6SConstantin Musca switch (mask) { 15132133be6SConstantin Musca case IIO_CHAN_INFO_RAW: 15232133be6SConstantin Musca mutex_lock(&data->lock); 15332133be6SConstantin Musca ret = mma7660_read_accel(data, chan->address); 15432133be6SConstantin Musca mutex_unlock(&data->lock); 15532133be6SConstantin Musca if (ret < 0) 15632133be6SConstantin Musca return ret; 15732133be6SConstantin Musca *val = sign_extend32(ret, 5); 15832133be6SConstantin Musca return IIO_VAL_INT; 15932133be6SConstantin Musca case IIO_CHAN_INFO_SCALE: 16032133be6SConstantin Musca *val = 0; 16132133be6SConstantin Musca *val2 = mma7660_nscale; 16232133be6SConstantin Musca return IIO_VAL_INT_PLUS_NANO; 16332133be6SConstantin Musca default: 16432133be6SConstantin Musca return -EINVAL; 16532133be6SConstantin Musca } 16632133be6SConstantin Musca 16732133be6SConstantin Musca return -EINVAL; 16832133be6SConstantin Musca } 16932133be6SConstantin Musca 17032133be6SConstantin Musca static const struct iio_info mma7660_info = { 17132133be6SConstantin Musca .driver_module = THIS_MODULE, 17232133be6SConstantin Musca .read_raw = mma7660_read_raw, 17332133be6SConstantin Musca .attrs = &mma7660_attribute_group, 17432133be6SConstantin Musca }; 17532133be6SConstantin Musca 17632133be6SConstantin Musca static int mma7660_probe(struct i2c_client *client, 17732133be6SConstantin Musca const struct i2c_device_id *id) 17832133be6SConstantin Musca { 17932133be6SConstantin Musca int ret; 18032133be6SConstantin Musca struct iio_dev *indio_dev; 18132133be6SConstantin Musca struct mma7660_data *data; 18232133be6SConstantin Musca 18332133be6SConstantin Musca indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 18432133be6SConstantin Musca if (!indio_dev) { 18532133be6SConstantin Musca dev_err(&client->dev, "iio allocation failed!\n"); 18632133be6SConstantin Musca return -ENOMEM; 18732133be6SConstantin Musca } 18832133be6SConstantin Musca 18932133be6SConstantin Musca data = iio_priv(indio_dev); 19032133be6SConstantin Musca data->client = client; 19132133be6SConstantin Musca i2c_set_clientdata(client, indio_dev); 19232133be6SConstantin Musca mutex_init(&data->lock); 19332133be6SConstantin Musca data->mode = MMA7660_MODE_STANDBY; 19432133be6SConstantin Musca 19532133be6SConstantin Musca indio_dev->dev.parent = &client->dev; 19632133be6SConstantin Musca indio_dev->info = &mma7660_info; 19732133be6SConstantin Musca indio_dev->name = MMA7660_DRIVER_NAME; 19832133be6SConstantin Musca indio_dev->modes = INDIO_DIRECT_MODE; 19932133be6SConstantin Musca indio_dev->channels = mma7660_channels; 20032133be6SConstantin Musca indio_dev->num_channels = ARRAY_SIZE(mma7660_channels); 20132133be6SConstantin Musca 20232133be6SConstantin Musca ret = mma7660_set_mode(data, MMA7660_MODE_ACTIVE); 20332133be6SConstantin Musca if (ret < 0) 20432133be6SConstantin Musca return ret; 20532133be6SConstantin Musca 20632133be6SConstantin Musca ret = iio_device_register(indio_dev); 20732133be6SConstantin Musca if (ret < 0) { 20832133be6SConstantin Musca dev_err(&client->dev, "device_register failed\n"); 20932133be6SConstantin Musca mma7660_set_mode(data, MMA7660_MODE_STANDBY); 21032133be6SConstantin Musca } 21132133be6SConstantin Musca 21232133be6SConstantin Musca return ret; 21332133be6SConstantin Musca } 21432133be6SConstantin Musca 21532133be6SConstantin Musca static int mma7660_remove(struct i2c_client *client) 21632133be6SConstantin Musca { 21732133be6SConstantin Musca struct iio_dev *indio_dev = i2c_get_clientdata(client); 21832133be6SConstantin Musca 21932133be6SConstantin Musca iio_device_unregister(indio_dev); 22032133be6SConstantin Musca 22132133be6SConstantin Musca return mma7660_set_mode(iio_priv(indio_dev), MMA7660_MODE_STANDBY); 22232133be6SConstantin Musca } 22332133be6SConstantin Musca 22432133be6SConstantin Musca #ifdef CONFIG_PM_SLEEP 22532133be6SConstantin Musca static int mma7660_suspend(struct device *dev) 22632133be6SConstantin Musca { 22732133be6SConstantin Musca struct mma7660_data *data; 22832133be6SConstantin Musca 22932133be6SConstantin Musca data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 23032133be6SConstantin Musca 23132133be6SConstantin Musca return mma7660_set_mode(data, MMA7660_MODE_STANDBY); 23232133be6SConstantin Musca } 23332133be6SConstantin Musca 23432133be6SConstantin Musca static int mma7660_resume(struct device *dev) 23532133be6SConstantin Musca { 23632133be6SConstantin Musca struct mma7660_data *data; 23732133be6SConstantin Musca 23832133be6SConstantin Musca data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 23932133be6SConstantin Musca 24032133be6SConstantin Musca return mma7660_set_mode(data, MMA7660_MODE_ACTIVE); 24132133be6SConstantin Musca } 24232133be6SConstantin Musca 24332133be6SConstantin Musca static SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend, mma7660_resume); 24432133be6SConstantin Musca 24532133be6SConstantin Musca #define MMA7660_PM_OPS (&mma7660_pm_ops) 24632133be6SConstantin Musca #else 24732133be6SConstantin Musca #define MMA7660_PM_OPS NULL 24832133be6SConstantin Musca #endif 24932133be6SConstantin Musca 25032133be6SConstantin Musca static const struct i2c_device_id mma7660_i2c_id[] = { 25132133be6SConstantin Musca {"mma7660", 0}, 25232133be6SConstantin Musca {} 25332133be6SConstantin Musca }; 254*56203188SHans de Goede MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id); 25532133be6SConstantin Musca 25632133be6SConstantin Musca static const struct acpi_device_id mma7660_acpi_id[] = { 25732133be6SConstantin Musca {"MMA7660", 0}, 25832133be6SConstantin Musca {} 25932133be6SConstantin Musca }; 26032133be6SConstantin Musca 26132133be6SConstantin Musca MODULE_DEVICE_TABLE(acpi, mma7660_acpi_id); 26232133be6SConstantin Musca 26332133be6SConstantin Musca static struct i2c_driver mma7660_driver = { 26432133be6SConstantin Musca .driver = { 26532133be6SConstantin Musca .name = "mma7660", 26632133be6SConstantin Musca .pm = MMA7660_PM_OPS, 26732133be6SConstantin Musca .acpi_match_table = ACPI_PTR(mma7660_acpi_id), 26832133be6SConstantin Musca }, 26932133be6SConstantin Musca .probe = mma7660_probe, 27032133be6SConstantin Musca .remove = mma7660_remove, 27132133be6SConstantin Musca .id_table = mma7660_i2c_id, 27232133be6SConstantin Musca }; 27332133be6SConstantin Musca 27432133be6SConstantin Musca module_i2c_driver(mma7660_driver); 27532133be6SConstantin Musca 27632133be6SConstantin Musca MODULE_AUTHOR("Constantin Musca <constantin.musca@intel.com>"); 27732133be6SConstantin Musca MODULE_DESCRIPTION("Freescale MMA7660FC 3-Axis Accelerometer driver"); 27832133be6SConstantin Musca MODULE_LICENSE("GPL v2"); 279