0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/delay.h>
0014 #include <linux/iio/iio.h>
0015 #include <linux/iio/sysfs.h>
0016 #include <linux/iio/buffer.h>
0017 #include <linux/iio/trigger.h>
0018 #include <linux/iio/trigger_consumer.h>
0019 #include <linux/iio/triggered_buffer.h>
0020 #include <linux/module.h>
0021 #include <linux/regmap.h>
0022
0023 #include "mma7455.h"
0024
0025 #define MMA7455_REG_XOUTL 0x00
0026 #define MMA7455_REG_XOUTH 0x01
0027 #define MMA7455_REG_YOUTL 0x02
0028 #define MMA7455_REG_YOUTH 0x03
0029 #define MMA7455_REG_ZOUTL 0x04
0030 #define MMA7455_REG_ZOUTH 0x05
0031 #define MMA7455_REG_STATUS 0x09
0032 #define MMA7455_STATUS_DRDY BIT(0)
0033 #define MMA7455_REG_WHOAMI 0x0f
0034 #define MMA7455_WHOAMI_ID 0x55
0035 #define MMA7455_REG_MCTL 0x16
0036 #define MMA7455_MCTL_MODE_STANDBY 0x00
0037 #define MMA7455_MCTL_MODE_MEASURE 0x01
0038 #define MMA7455_REG_CTL1 0x18
0039 #define MMA7455_CTL1_DFBW_MASK BIT(7)
0040 #define MMA7455_CTL1_DFBW_125HZ BIT(7)
0041 #define MMA7455_CTL1_DFBW_62_5HZ 0
0042 #define MMA7455_REG_TW 0x1e
0043
0044
0045
0046
0047
0048
0049
0050
0051 #define MMA7455_10BIT_SCALE 153229
0052
0053 struct mma7455_data {
0054 struct regmap *regmap;
0055
0056
0057
0058
0059 struct {
0060 __le16 channels[3];
0061 s64 ts __aligned(8);
0062 } scan;
0063 };
0064
0065 static int mma7455_drdy(struct mma7455_data *mma7455)
0066 {
0067 struct device *dev = regmap_get_device(mma7455->regmap);
0068 unsigned int reg;
0069 int tries = 3;
0070 int ret;
0071
0072 while (tries-- > 0) {
0073 ret = regmap_read(mma7455->regmap, MMA7455_REG_STATUS, ®);
0074 if (ret)
0075 return ret;
0076
0077 if (reg & MMA7455_STATUS_DRDY)
0078 return 0;
0079
0080 msleep(20);
0081 }
0082
0083 dev_warn(dev, "data not ready\n");
0084
0085 return -EIO;
0086 }
0087
0088 static irqreturn_t mma7455_trigger_handler(int irq, void *p)
0089 {
0090 struct iio_poll_func *pf = p;
0091 struct iio_dev *indio_dev = pf->indio_dev;
0092 struct mma7455_data *mma7455 = iio_priv(indio_dev);
0093 int ret;
0094
0095 ret = mma7455_drdy(mma7455);
0096 if (ret)
0097 goto done;
0098
0099 ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL,
0100 mma7455->scan.channels,
0101 sizeof(mma7455->scan.channels));
0102 if (ret)
0103 goto done;
0104
0105 iio_push_to_buffers_with_timestamp(indio_dev, &mma7455->scan,
0106 iio_get_time_ns(indio_dev));
0107
0108 done:
0109 iio_trigger_notify_done(indio_dev->trig);
0110
0111 return IRQ_HANDLED;
0112 }
0113
0114 static int mma7455_read_raw(struct iio_dev *indio_dev,
0115 struct iio_chan_spec const *chan,
0116 int *val, int *val2, long mask)
0117 {
0118 struct mma7455_data *mma7455 = iio_priv(indio_dev);
0119 unsigned int reg;
0120 __le16 data;
0121 int ret;
0122
0123 switch (mask) {
0124 case IIO_CHAN_INFO_RAW:
0125 if (iio_buffer_enabled(indio_dev))
0126 return -EBUSY;
0127
0128 ret = mma7455_drdy(mma7455);
0129 if (ret)
0130 return ret;
0131
0132 ret = regmap_bulk_read(mma7455->regmap, chan->address, &data,
0133 sizeof(data));
0134 if (ret)
0135 return ret;
0136
0137 *val = sign_extend32(le16_to_cpu(data),
0138 chan->scan_type.realbits - 1);
0139
0140 return IIO_VAL_INT;
0141
0142 case IIO_CHAN_INFO_SCALE:
0143 *val = 0;
0144 *val2 = MMA7455_10BIT_SCALE;
0145
0146 return IIO_VAL_INT_PLUS_MICRO;
0147
0148 case IIO_CHAN_INFO_SAMP_FREQ:
0149 ret = regmap_read(mma7455->regmap, MMA7455_REG_CTL1, ®);
0150 if (ret)
0151 return ret;
0152
0153 if (reg & MMA7455_CTL1_DFBW_MASK)
0154 *val = 250;
0155 else
0156 *val = 125;
0157
0158 return IIO_VAL_INT;
0159 }
0160
0161 return -EINVAL;
0162 }
0163
0164 static int mma7455_write_raw(struct iio_dev *indio_dev,
0165 struct iio_chan_spec const *chan,
0166 int val, int val2, long mask)
0167 {
0168 struct mma7455_data *mma7455 = iio_priv(indio_dev);
0169 int i;
0170
0171 switch (mask) {
0172 case IIO_CHAN_INFO_SAMP_FREQ:
0173 if (val == 250 && val2 == 0)
0174 i = MMA7455_CTL1_DFBW_125HZ;
0175 else if (val == 125 && val2 == 0)
0176 i = MMA7455_CTL1_DFBW_62_5HZ;
0177 else
0178 return -EINVAL;
0179
0180 return regmap_update_bits(mma7455->regmap, MMA7455_REG_CTL1,
0181 MMA7455_CTL1_DFBW_MASK, i);
0182
0183 case IIO_CHAN_INFO_SCALE:
0184
0185 if (val == 0 && val2 == MMA7455_10BIT_SCALE)
0186 return 0;
0187 break;
0188 }
0189
0190 return -EINVAL;
0191 }
0192
0193 static IIO_CONST_ATTR(sampling_frequency_available, "125 250");
0194
0195 static struct attribute *mma7455_attributes[] = {
0196 &iio_const_attr_sampling_frequency_available.dev_attr.attr,
0197 NULL
0198 };
0199
0200 static const struct attribute_group mma7455_group = {
0201 .attrs = mma7455_attributes,
0202 };
0203
0204 static const struct iio_info mma7455_info = {
0205 .attrs = &mma7455_group,
0206 .read_raw = mma7455_read_raw,
0207 .write_raw = mma7455_write_raw,
0208 };
0209
0210 #define MMA7455_CHANNEL(axis, idx) { \
0211 .type = IIO_ACCEL, \
0212 .modified = 1, \
0213 .address = MMA7455_REG_##axis##OUTL,\
0214 .channel2 = IIO_MOD_##axis, \
0215 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0216 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
0217 BIT(IIO_CHAN_INFO_SCALE), \
0218 .scan_index = idx, \
0219 .scan_type = { \
0220 .sign = 's', \
0221 .realbits = 10, \
0222 .storagebits = 16, \
0223 .endianness = IIO_LE, \
0224 }, \
0225 }
0226
0227 static const struct iio_chan_spec mma7455_channels[] = {
0228 MMA7455_CHANNEL(X, 0),
0229 MMA7455_CHANNEL(Y, 1),
0230 MMA7455_CHANNEL(Z, 2),
0231 IIO_CHAN_SOFT_TIMESTAMP(3),
0232 };
0233
0234 static const unsigned long mma7455_scan_masks[] = {0x7, 0};
0235
0236 const struct regmap_config mma7455_core_regmap = {
0237 .reg_bits = 8,
0238 .val_bits = 8,
0239 .max_register = MMA7455_REG_TW,
0240 };
0241 EXPORT_SYMBOL_NS_GPL(mma7455_core_regmap, IIO_MMA7455);
0242
0243 int mma7455_core_probe(struct device *dev, struct regmap *regmap,
0244 const char *name)
0245 {
0246 struct mma7455_data *mma7455;
0247 struct iio_dev *indio_dev;
0248 unsigned int reg;
0249 int ret;
0250
0251 ret = regmap_read(regmap, MMA7455_REG_WHOAMI, ®);
0252 if (ret) {
0253 dev_err(dev, "unable to read reg\n");
0254 return ret;
0255 }
0256
0257 if (reg != MMA7455_WHOAMI_ID) {
0258 dev_err(dev, "device id mismatch\n");
0259 return -ENODEV;
0260 }
0261
0262 indio_dev = devm_iio_device_alloc(dev, sizeof(*mma7455));
0263 if (!indio_dev)
0264 return -ENOMEM;
0265
0266 dev_set_drvdata(dev, indio_dev);
0267 mma7455 = iio_priv(indio_dev);
0268 mma7455->regmap = regmap;
0269
0270 indio_dev->info = &mma7455_info;
0271 indio_dev->name = name;
0272 indio_dev->modes = INDIO_DIRECT_MODE;
0273 indio_dev->channels = mma7455_channels;
0274 indio_dev->num_channels = ARRAY_SIZE(mma7455_channels);
0275 indio_dev->available_scan_masks = mma7455_scan_masks;
0276
0277 regmap_write(mma7455->regmap, MMA7455_REG_MCTL,
0278 MMA7455_MCTL_MODE_MEASURE);
0279
0280 ret = iio_triggered_buffer_setup(indio_dev, NULL,
0281 mma7455_trigger_handler, NULL);
0282 if (ret) {
0283 dev_err(dev, "unable to setup triggered buffer\n");
0284 return ret;
0285 }
0286
0287 ret = iio_device_register(indio_dev);
0288 if (ret) {
0289 dev_err(dev, "unable to register device\n");
0290 iio_triggered_buffer_cleanup(indio_dev);
0291 return ret;
0292 }
0293
0294 return 0;
0295 }
0296 EXPORT_SYMBOL_NS_GPL(mma7455_core_probe, IIO_MMA7455);
0297
0298 void mma7455_core_remove(struct device *dev)
0299 {
0300 struct iio_dev *indio_dev = dev_get_drvdata(dev);
0301 struct mma7455_data *mma7455 = iio_priv(indio_dev);
0302
0303 iio_device_unregister(indio_dev);
0304 iio_triggered_buffer_cleanup(indio_dev);
0305
0306 regmap_write(mma7455->regmap, MMA7455_REG_MCTL,
0307 MMA7455_MCTL_MODE_STANDBY);
0308 }
0309 EXPORT_SYMBOL_NS_GPL(mma7455_core_remove, IIO_MMA7455);
0310
0311 MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
0312 MODULE_DESCRIPTION("Freescale MMA7455L core accelerometer driver");
0313 MODULE_LICENSE("GPL v2");