1 /* 2 * ADXL345 3-Axis Digital Accelerometer IIO core driver 3 * 4 * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com> 5 * 6 * This file is subject to the terms and conditions of version 2 of 7 * the GNU General Public License. See the file COPYING in the main 8 * directory of this archive for more details. 9 */ 10 11 #include <linux/module.h> 12 #include <linux/regmap.h> 13 14 #include <linux/iio/iio.h> 15 16 #include "adxl345.h" 17 18 #define ADXL345_REG_DEVID 0x00 19 #define ADXL345_REG_POWER_CTL 0x2D 20 #define ADXL345_REG_DATA_FORMAT 0x31 21 #define ADXL345_REG_DATAX0 0x32 22 #define ADXL345_REG_DATAY0 0x34 23 #define ADXL345_REG_DATAZ0 0x36 24 25 #define ADXL345_POWER_CTL_MEASURE BIT(3) 26 #define ADXL345_POWER_CTL_STANDBY 0x00 27 28 #define ADXL345_DATA_FORMAT_FULL_RES BIT(3) /* Up to 13-bits resolution */ 29 #define ADXL345_DATA_FORMAT_2G 0 30 #define ADXL345_DATA_FORMAT_4G 1 31 #define ADXL345_DATA_FORMAT_8G 2 32 #define ADXL345_DATA_FORMAT_16G 3 33 34 #define ADXL345_DEVID 0xE5 35 36 /* 37 * In full-resolution mode, scale factor is maintained at ~4 mg/LSB 38 * in all g ranges. 39 * 40 * At +/- 16g with 13-bit resolution, scale is computed as: 41 * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383 42 */ 43 static const int adxl345_uscale = 38300; 44 45 struct adxl345_data { 46 struct regmap *regmap; 47 u8 data_range; 48 }; 49 50 #define ADXL345_CHANNEL(reg, axis) { \ 51 .type = IIO_ACCEL, \ 52 .modified = 1, \ 53 .channel2 = IIO_MOD_##axis, \ 54 .address = reg, \ 55 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 56 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 57 } 58 59 static const struct iio_chan_spec adxl345_channels[] = { 60 ADXL345_CHANNEL(ADXL345_REG_DATAX0, X), 61 ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y), 62 ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z), 63 }; 64 65 static int adxl345_read_raw(struct iio_dev *indio_dev, 66 struct iio_chan_spec const *chan, 67 int *val, int *val2, long mask) 68 { 69 struct adxl345_data *data = iio_priv(indio_dev); 70 __le16 regval; 71 int ret; 72 73 switch (mask) { 74 case IIO_CHAN_INFO_RAW: 75 /* 76 * Data is stored in adjacent registers: 77 * ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte 78 * and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte 79 */ 80 ret = regmap_bulk_read(data->regmap, chan->address, ®val, 81 sizeof(regval)); 82 if (ret < 0) 83 return ret; 84 85 *val = sign_extend32(le16_to_cpu(regval), 12); 86 return IIO_VAL_INT; 87 case IIO_CHAN_INFO_SCALE: 88 *val = 0; 89 *val2 = adxl345_uscale; 90 91 return IIO_VAL_INT_PLUS_MICRO; 92 } 93 94 return -EINVAL; 95 } 96 97 static const struct iio_info adxl345_info = { 98 .read_raw = adxl345_read_raw, 99 }; 100 101 int adxl345_core_probe(struct device *dev, struct regmap *regmap, 102 const char *name) 103 { 104 struct adxl345_data *data; 105 struct iio_dev *indio_dev; 106 u32 regval; 107 int ret; 108 109 ret = regmap_read(regmap, ADXL345_REG_DEVID, ®val); 110 if (ret < 0) { 111 dev_err(dev, "Error reading device ID: %d\n", ret); 112 return ret; 113 } 114 115 if (regval != ADXL345_DEVID) { 116 dev_err(dev, "Invalid device ID: %x, expected %x\n", 117 regval, ADXL345_DEVID); 118 return -ENODEV; 119 } 120 121 indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 122 if (!indio_dev) 123 return -ENOMEM; 124 125 data = iio_priv(indio_dev); 126 dev_set_drvdata(dev, indio_dev); 127 data->regmap = regmap; 128 /* Enable full-resolution mode */ 129 data->data_range = ADXL345_DATA_FORMAT_FULL_RES; 130 131 ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT, 132 data->data_range); 133 if (ret < 0) { 134 dev_err(dev, "Failed to set data range: %d\n", ret); 135 return ret; 136 } 137 138 indio_dev->dev.parent = dev; 139 indio_dev->name = name; 140 indio_dev->info = &adxl345_info; 141 indio_dev->modes = INDIO_DIRECT_MODE; 142 indio_dev->channels = adxl345_channels; 143 indio_dev->num_channels = ARRAY_SIZE(adxl345_channels); 144 145 /* Enable measurement mode */ 146 ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL, 147 ADXL345_POWER_CTL_MEASURE); 148 if (ret < 0) { 149 dev_err(dev, "Failed to enable measurement mode: %d\n", ret); 150 return ret; 151 } 152 153 ret = iio_device_register(indio_dev); 154 if (ret < 0) { 155 dev_err(dev, "iio_device_register failed: %d\n", ret); 156 regmap_write(data->regmap, ADXL345_REG_POWER_CTL, 157 ADXL345_POWER_CTL_STANDBY); 158 } 159 160 return ret; 161 } 162 EXPORT_SYMBOL_GPL(adxl345_core_probe); 163 164 int adxl345_core_remove(struct device *dev) 165 { 166 struct iio_dev *indio_dev = dev_get_drvdata(dev); 167 struct adxl345_data *data = iio_priv(indio_dev); 168 169 iio_device_unregister(indio_dev); 170 171 return regmap_write(data->regmap, ADXL345_REG_POWER_CTL, 172 ADXL345_POWER_CTL_STANDBY); 173 } 174 EXPORT_SYMBOL_GPL(adxl345_core_remove); 175 176 MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>"); 177 MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver"); 178 MODULE_LICENSE("GPL v2"); 179