1 /** 2 * IIO driver for the MiraMEMS DA311 3-axis accelerometer 3 * 4 * Copyright (c) 2016 Hans de Goede <hdegoede@redhat.com> 5 * Copyright (c) 2011-2013 MiraMEMS Sensing Technology Co., Ltd. 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/iio/iio.h> 15 #include <linux/iio/sysfs.h> 16 #include <linux/byteorder/generic.h> 17 18 #define DA311_CHIP_ID 0x13 19 20 /* 21 * Note register addressed go from 0 - 0x3f and then wrap. 22 * For some reason there are 2 banks with 0 - 0x3f addresses, 23 * rather then a single 0-0x7f bank. 24 */ 25 26 /* Bank 0 regs */ 27 #define DA311_REG_BANK 0x0000 28 #define DA311_REG_LDO_REG 0x0006 29 #define DA311_REG_CHIP_ID 0x000f 30 #define DA311_REG_TEMP_CFG_REG 0x001f 31 #define DA311_REG_CTRL_REG1 0x0020 32 #define DA311_REG_CTRL_REG3 0x0022 33 #define DA311_REG_CTRL_REG4 0x0023 34 #define DA311_REG_CTRL_REG5 0x0024 35 #define DA311_REG_CTRL_REG6 0x0025 36 #define DA311_REG_STATUS_REG 0x0027 37 #define DA311_REG_OUT_X_L 0x0028 38 #define DA311_REG_OUT_X_H 0x0029 39 #define DA311_REG_OUT_Y_L 0x002a 40 #define DA311_REG_OUT_Y_H 0x002b 41 #define DA311_REG_OUT_Z_L 0x002c 42 #define DA311_REG_OUT_Z_H 0x002d 43 #define DA311_REG_INT1_CFG 0x0030 44 #define DA311_REG_INT1_SRC 0x0031 45 #define DA311_REG_INT1_THS 0x0032 46 #define DA311_REG_INT1_DURATION 0x0033 47 #define DA311_REG_INT2_CFG 0x0034 48 #define DA311_REG_INT2_SRC 0x0035 49 #define DA311_REG_INT2_THS 0x0036 50 #define DA311_REG_INT2_DURATION 0x0037 51 #define DA311_REG_CLICK_CFG 0x0038 52 #define DA311_REG_CLICK_SRC 0x0039 53 #define DA311_REG_CLICK_THS 0x003a 54 #define DA311_REG_TIME_LIMIT 0x003b 55 #define DA311_REG_TIME_LATENCY 0x003c 56 #define DA311_REG_TIME_WINDOW 0x003d 57 58 /* Bank 1 regs */ 59 #define DA311_REG_SOFT_RESET 0x0105 60 #define DA311_REG_OTP_XOFF_L 0x0110 61 #define DA311_REG_OTP_XOFF_H 0x0111 62 #define DA311_REG_OTP_YOFF_L 0x0112 63 #define DA311_REG_OTP_YOFF_H 0x0113 64 #define DA311_REG_OTP_ZOFF_L 0x0114 65 #define DA311_REG_OTP_ZOFF_H 0x0115 66 #define DA311_REG_OTP_XSO 0x0116 67 #define DA311_REG_OTP_YSO 0x0117 68 #define DA311_REG_OTP_ZSO 0x0118 69 #define DA311_REG_OTP_TRIM_OSC 0x011b 70 #define DA311_REG_LPF_ABSOLUTE 0x011c 71 #define DA311_REG_TEMP_OFF1 0x0127 72 #define DA311_REG_TEMP_OFF2 0x0128 73 #define DA311_REG_TEMP_OFF3 0x0129 74 #define DA311_REG_OTP_TRIM_THERM_H 0x011a 75 76 /* 77 * a value of + or -1024 corresponds to + or - 1G 78 * scale = 9.81 / 1024 = 0.009580078 79 */ 80 81 static const int da311_nscale = 9580078; 82 83 #define DA311_CHANNEL(reg, axis) { \ 84 .type = IIO_ACCEL, \ 85 .address = reg, \ 86 .modified = 1, \ 87 .channel2 = IIO_MOD_##axis, \ 88 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 89 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 90 } 91 92 static const struct iio_chan_spec da311_channels[] = { 93 /* | 0x80 comes from the android driver */ 94 DA311_CHANNEL(DA311_REG_OUT_X_L | 0x80, X), 95 DA311_CHANNEL(DA311_REG_OUT_Y_L | 0x80, Y), 96 DA311_CHANNEL(DA311_REG_OUT_Z_L | 0x80, Z), 97 }; 98 99 struct da311_data { 100 struct i2c_client *client; 101 }; 102 103 static int da311_register_mask_write(struct i2c_client *client, u16 addr, 104 u8 mask, u8 data) 105 { 106 int ret; 107 u8 tmp_data = 0; 108 109 if (addr & 0xff00) { 110 /* Select bank 1 */ 111 ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x01); 112 if (ret < 0) 113 return ret; 114 } 115 116 if (mask != 0xff) { 117 ret = i2c_smbus_read_byte_data(client, addr); 118 if (ret < 0) 119 return ret; 120 tmp_data = ret; 121 } 122 123 tmp_data &= ~mask; 124 tmp_data |= data & mask; 125 ret = i2c_smbus_write_byte_data(client, addr & 0xff, tmp_data); 126 if (ret < 0) 127 return ret; 128 129 if (addr & 0xff00) { 130 /* Back to bank 0 */ 131 ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x00); 132 if (ret < 0) 133 return ret; 134 } 135 136 return 0; 137 } 138 139 /* Init sequence taken from the android driver */ 140 static int da311_reset(struct i2c_client *client) 141 { 142 static const struct { 143 u16 addr; 144 u8 mask; 145 u8 data; 146 } init_data[] = { 147 { DA311_REG_TEMP_CFG_REG, 0xff, 0x08 }, 148 { DA311_REG_CTRL_REG5, 0xff, 0x80 }, 149 { DA311_REG_CTRL_REG4, 0x30, 0x00 }, 150 { DA311_REG_CTRL_REG1, 0xff, 0x6f }, 151 { DA311_REG_TEMP_CFG_REG, 0xff, 0x88 }, 152 { DA311_REG_LDO_REG, 0xff, 0x02 }, 153 { DA311_REG_OTP_TRIM_OSC, 0xff, 0x27 }, 154 { DA311_REG_LPF_ABSOLUTE, 0xff, 0x30 }, 155 { DA311_REG_TEMP_OFF1, 0xff, 0x3f }, 156 { DA311_REG_TEMP_OFF2, 0xff, 0xff }, 157 { DA311_REG_TEMP_OFF3, 0xff, 0x0f }, 158 }; 159 int i, ret; 160 161 /* Reset */ 162 ret = da311_register_mask_write(client, DA311_REG_SOFT_RESET, 163 0xff, 0xaa); 164 if (ret < 0) 165 return ret; 166 167 for (i = 0; i < ARRAY_SIZE(init_data); i++) { 168 ret = da311_register_mask_write(client, 169 init_data[i].addr, 170 init_data[i].mask, 171 init_data[i].data); 172 if (ret < 0) 173 return ret; 174 } 175 176 return 0; 177 } 178 179 static int da311_enable(struct i2c_client *client, bool enable) 180 { 181 u8 data = enable ? 0x00 : 0x20; 182 183 return da311_register_mask_write(client, DA311_REG_TEMP_CFG_REG, 184 0x20, data); 185 } 186 187 static int da311_read_raw(struct iio_dev *indio_dev, 188 struct iio_chan_spec const *chan, 189 int *val, int *val2, long mask) 190 { 191 struct da311_data *data = iio_priv(indio_dev); 192 int ret; 193 194 switch (mask) { 195 case IIO_CHAN_INFO_RAW: 196 ret = i2c_smbus_read_word_data(data->client, chan->address); 197 if (ret < 0) 198 return ret; 199 /* 200 * Values are 12 bits, stored as 16 bits with the 4 201 * least significant bits always 0. 202 */ 203 *val = (short)ret >> 4; 204 return IIO_VAL_INT; 205 case IIO_CHAN_INFO_SCALE: 206 *val = 0; 207 *val2 = da311_nscale; 208 return IIO_VAL_INT_PLUS_NANO; 209 default: 210 return -EINVAL; 211 } 212 } 213 214 static const struct iio_info da311_info = { 215 .read_raw = da311_read_raw, 216 }; 217 218 static int da311_probe(struct i2c_client *client, 219 const struct i2c_device_id *id) 220 { 221 int ret; 222 struct iio_dev *indio_dev; 223 struct da311_data *data; 224 225 ret = i2c_smbus_read_byte_data(client, DA311_REG_CHIP_ID); 226 if (ret != DA311_CHIP_ID) 227 return (ret < 0) ? ret : -ENODEV; 228 229 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 230 if (!indio_dev) 231 return -ENOMEM; 232 233 data = iio_priv(indio_dev); 234 data->client = client; 235 i2c_set_clientdata(client, indio_dev); 236 237 indio_dev->dev.parent = &client->dev; 238 indio_dev->info = &da311_info; 239 indio_dev->name = "da311"; 240 indio_dev->modes = INDIO_DIRECT_MODE; 241 indio_dev->channels = da311_channels; 242 indio_dev->num_channels = ARRAY_SIZE(da311_channels); 243 244 ret = da311_reset(client); 245 if (ret < 0) 246 return ret; 247 248 ret = da311_enable(client, true); 249 if (ret < 0) 250 return ret; 251 252 ret = iio_device_register(indio_dev); 253 if (ret < 0) { 254 dev_err(&client->dev, "device_register failed\n"); 255 da311_enable(client, false); 256 } 257 258 return ret; 259 } 260 261 static int da311_remove(struct i2c_client *client) 262 { 263 struct iio_dev *indio_dev = i2c_get_clientdata(client); 264 265 iio_device_unregister(indio_dev); 266 267 return da311_enable(client, false); 268 } 269 270 #ifdef CONFIG_PM_SLEEP 271 static int da311_suspend(struct device *dev) 272 { 273 return da311_enable(to_i2c_client(dev), false); 274 } 275 276 static int da311_resume(struct device *dev) 277 { 278 return da311_enable(to_i2c_client(dev), true); 279 } 280 #endif 281 282 static SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume); 283 284 static const struct i2c_device_id da311_i2c_id[] = { 285 {"da311", 0}, 286 {} 287 }; 288 MODULE_DEVICE_TABLE(i2c, da311_i2c_id); 289 290 static struct i2c_driver da311_driver = { 291 .driver = { 292 .name = "da311", 293 .pm = &da311_pm_ops, 294 }, 295 .probe = da311_probe, 296 .remove = da311_remove, 297 .id_table = da311_i2c_id, 298 }; 299 300 module_i2c_driver(da311_driver); 301 302 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 303 MODULE_DESCRIPTION("MiraMEMS DA311 3-Axis Accelerometer driver"); 304 MODULE_LICENSE("GPL v2"); 305