root/drivers/iio/accel/da311.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. da311_register_mask_write
  2. da311_reset
  3. da311_enable
  4. da311_read_raw
  5. da311_probe
  6. da311_remove
  7. da311_suspend
  8. da311_resume

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

/* [<][>][^][v][top][bottom][index][help] */