1 /** 2 * IIO driver for the MiraMEMS DA280 3-axis accelerometer and 3 * IIO driver for the MiraMEMS DA226 2-axis accelerometer 4 * 5 * Copyright (c) 2016 Hans de Goede <hdegoede@redhat.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms and conditions of the GNU General Public License, 9 * version 2, as published by the Free Software Foundation. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/i2c.h> 14 #include <linux/acpi.h> 15 #include <linux/iio/iio.h> 16 #include <linux/iio/sysfs.h> 17 #include <linux/byteorder/generic.h> 18 19 #define DA280_REG_CHIP_ID 0x01 20 #define DA280_REG_ACC_X_LSB 0x02 21 #define DA280_REG_ACC_Y_LSB 0x04 22 #define DA280_REG_ACC_Z_LSB 0x06 23 #define DA280_REG_MODE_BW 0x11 24 25 #define DA280_CHIP_ID 0x13 26 #define DA280_MODE_ENABLE 0x1e 27 #define DA280_MODE_DISABLE 0x9e 28 29 enum da280_chipset { da226, da280 }; 30 31 /* 32 * a value of + or -4096 corresponds to + or - 1G 33 * scale = 9.81 / 4096 = 0.002395019 34 */ 35 36 static const int da280_nscale = 2395019; 37 38 #define DA280_CHANNEL(reg, axis) { \ 39 .type = IIO_ACCEL, \ 40 .address = reg, \ 41 .modified = 1, \ 42 .channel2 = IIO_MOD_##axis, \ 43 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 44 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 45 } 46 47 static const struct iio_chan_spec da280_channels[] = { 48 DA280_CHANNEL(DA280_REG_ACC_X_LSB, X), 49 DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y), 50 DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z), 51 }; 52 53 struct da280_data { 54 struct i2c_client *client; 55 }; 56 57 static int da280_enable(struct i2c_client *client, bool enable) 58 { 59 u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE; 60 61 return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data); 62 } 63 64 static int da280_read_raw(struct iio_dev *indio_dev, 65 struct iio_chan_spec const *chan, 66 int *val, int *val2, long mask) 67 { 68 struct da280_data *data = iio_priv(indio_dev); 69 int ret; 70 71 switch (mask) { 72 case IIO_CHAN_INFO_RAW: 73 ret = i2c_smbus_read_word_data(data->client, chan->address); 74 if (ret < 0) 75 return ret; 76 /* 77 * Values are 14 bits, stored as 16 bits with the 2 78 * least significant bits always 0. 79 */ 80 *val = (short)ret >> 2; 81 return IIO_VAL_INT; 82 case IIO_CHAN_INFO_SCALE: 83 *val = 0; 84 *val2 = da280_nscale; 85 return IIO_VAL_INT_PLUS_NANO; 86 default: 87 return -EINVAL; 88 } 89 } 90 91 static const struct iio_info da280_info = { 92 .read_raw = da280_read_raw, 93 }; 94 95 static enum da280_chipset da280_match_acpi_device(struct device *dev) 96 { 97 const struct acpi_device_id *id; 98 99 id = acpi_match_device(dev->driver->acpi_match_table, dev); 100 if (!id) 101 return -EINVAL; 102 103 return (enum da280_chipset) id->driver_data; 104 } 105 106 static int da280_probe(struct i2c_client *client, 107 const struct i2c_device_id *id) 108 { 109 int ret; 110 struct iio_dev *indio_dev; 111 struct da280_data *data; 112 enum da280_chipset chip; 113 114 ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID); 115 if (ret != DA280_CHIP_ID) 116 return (ret < 0) ? ret : -ENODEV; 117 118 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 119 if (!indio_dev) 120 return -ENOMEM; 121 122 data = iio_priv(indio_dev); 123 data->client = client; 124 i2c_set_clientdata(client, indio_dev); 125 126 indio_dev->dev.parent = &client->dev; 127 indio_dev->info = &da280_info; 128 indio_dev->modes = INDIO_DIRECT_MODE; 129 indio_dev->channels = da280_channels; 130 131 if (ACPI_HANDLE(&client->dev)) { 132 chip = da280_match_acpi_device(&client->dev); 133 } else { 134 chip = id->driver_data; 135 } 136 137 if (chip == da226) { 138 indio_dev->name = "da226"; 139 indio_dev->num_channels = 2; 140 } else { 141 indio_dev->name = "da280"; 142 indio_dev->num_channels = 3; 143 } 144 145 ret = da280_enable(client, true); 146 if (ret < 0) 147 return ret; 148 149 ret = iio_device_register(indio_dev); 150 if (ret < 0) { 151 dev_err(&client->dev, "device_register failed\n"); 152 da280_enable(client, false); 153 } 154 155 return ret; 156 } 157 158 static int da280_remove(struct i2c_client *client) 159 { 160 struct iio_dev *indio_dev = i2c_get_clientdata(client); 161 162 iio_device_unregister(indio_dev); 163 164 return da280_enable(client, false); 165 } 166 167 #ifdef CONFIG_PM_SLEEP 168 static int da280_suspend(struct device *dev) 169 { 170 return da280_enable(to_i2c_client(dev), false); 171 } 172 173 static int da280_resume(struct device *dev) 174 { 175 return da280_enable(to_i2c_client(dev), true); 176 } 177 #endif 178 179 static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume); 180 181 static const struct acpi_device_id da280_acpi_match[] = { 182 {"MIRAACC", da280}, 183 {}, 184 }; 185 MODULE_DEVICE_TABLE(acpi, da280_acpi_match); 186 187 static const struct i2c_device_id da280_i2c_id[] = { 188 { "da226", da226 }, 189 { "da280", da280 }, 190 {} 191 }; 192 MODULE_DEVICE_TABLE(i2c, da280_i2c_id); 193 194 static struct i2c_driver da280_driver = { 195 .driver = { 196 .name = "da280", 197 .acpi_match_table = ACPI_PTR(da280_acpi_match), 198 .pm = &da280_pm_ops, 199 }, 200 .probe = da280_probe, 201 .remove = da280_remove, 202 .id_table = da280_i2c_id, 203 }; 204 205 module_i2c_driver(da280_driver); 206 207 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 208 MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver"); 209 MODULE_LICENSE("GPL v2"); 210