2 * mma8452.c - Support for Freescale MMA8452Q 3-axis 12-bit accelerometer
4 * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
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.
10 * 7-bit I2C slave address 0x1c/0x1d (pin selectable)
12 * TODO: interrupt, thresholding, orientation / freefall events, autosleep
15 #include <linux/module.h>
16 #include <linux/i2c.h>
17 #include <linux/iio/iio.h>
18 #include <linux/iio/sysfs.h>
19 #include <linux/iio/trigger_consumer.h>
20 #include <linux/iio/buffer.h>
21 #include <linux/iio/triggered_buffer.h>
22 #include <linux/delay.h>
24 #define MMA8452_STATUS 0x00
25 #define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */
26 #define MMA8452_OUT_Y 0x03
27 #define MMA8452_OUT_Z 0x05
28 #define MMA8452_WHO_AM_I 0x0d
29 #define MMA8452_DATA_CFG 0x0e
30 #define MMA8452_OFF_X 0x2f
31 #define MMA8452_OFF_Y 0x30
32 #define MMA8452_OFF_Z 0x31
33 #define MMA8452_CTRL_REG1 0x2a
34 #define MMA8452_CTRL_REG2 0x2b
36 #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
38 #define MMA8452_CTRL_DR_MASK (BIT(5) | BIT(4) | BIT(3))
39 #define MMA8452_CTRL_DR_SHIFT 3
40 #define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
41 #define MMA8452_CTRL_ACTIVE BIT(0)
43 #define MMA8452_DATA_CFG_FS_MASK (BIT(1) | BIT(0))
44 #define MMA8452_DATA_CFG_FS_2G 0
45 #define MMA8452_DATA_CFG_FS_4G 1
46 #define MMA8452_DATA_CFG_FS_8G 2
48 #define MMA8452_DEVICE_ID 0x2a
51 struct i2c_client
*client
;
57 static int mma8452_drdy(struct mma8452_data
*data
)
62 int ret
= i2c_smbus_read_byte_data(data
->client
,
66 if ((ret
& MMA8452_STATUS_DRDY
) == MMA8452_STATUS_DRDY
)
71 dev_err(&data
->client
->dev
, "data not ready\n");
75 static int mma8452_read(struct mma8452_data
*data
, __be16 buf
[3])
77 int ret
= mma8452_drdy(data
);
80 return i2c_smbus_read_i2c_block_data(data
->client
,
81 MMA8452_OUT_X
, 3 * sizeof(__be16
), (u8
*) buf
);
84 static ssize_t
mma8452_show_int_plus_micros(char *buf
,
85 const int (*vals
)[2], int n
)
90 len
+= scnprintf(buf
+ len
, PAGE_SIZE
- len
,
91 "%d.%06d ", vals
[n
][0], vals
[n
][1]);
93 /* replace trailing space by newline */
99 static int mma8452_get_int_plus_micros_index(const int (*vals
)[2], int n
,
103 if (val
== vals
[n
][0] && val2
== vals
[n
][1])
109 static const int mma8452_samp_freq
[8][2] = {
110 {800, 0}, {400, 0}, {200, 0}, {100, 0}, {50, 0}, {12, 500000},
111 {6, 250000}, {1, 560000}
115 * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
116 * The userspace interface uses m/s^2 and we declare micro units
117 * So scale factor is given by:
118 * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
120 static const int mma8452_scales
[3][2] = {
121 {0, 9577}, {0, 19154}, {0, 38307}
124 static ssize_t
mma8452_show_samp_freq_avail(struct device
*dev
,
125 struct device_attribute
*attr
, char *buf
)
127 return mma8452_show_int_plus_micros(buf
, mma8452_samp_freq
,
128 ARRAY_SIZE(mma8452_samp_freq
));
131 static ssize_t
mma8452_show_scale_avail(struct device
*dev
,
132 struct device_attribute
*attr
, char *buf
)
134 return mma8452_show_int_plus_micros(buf
, mma8452_scales
,
135 ARRAY_SIZE(mma8452_scales
));
138 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail
);
139 static IIO_DEVICE_ATTR(in_accel_scale_available
, S_IRUGO
,
140 mma8452_show_scale_avail
, NULL
, 0);
142 static int mma8452_get_samp_freq_index(struct mma8452_data
*data
,
145 return mma8452_get_int_plus_micros_index(mma8452_samp_freq
,
146 ARRAY_SIZE(mma8452_samp_freq
), val
, val2
);
149 static int mma8452_get_scale_index(struct mma8452_data
*data
,
152 return mma8452_get_int_plus_micros_index(mma8452_scales
,
153 ARRAY_SIZE(mma8452_scales
), val
, val2
);
156 static int mma8452_read_raw(struct iio_dev
*indio_dev
,
157 struct iio_chan_spec
const *chan
,
158 int *val
, int *val2
, long mask
)
160 struct mma8452_data
*data
= iio_priv(indio_dev
);
165 case IIO_CHAN_INFO_RAW
:
166 if (iio_buffer_enabled(indio_dev
))
169 mutex_lock(&data
->lock
);
170 ret
= mma8452_read(data
, buffer
);
171 mutex_unlock(&data
->lock
);
174 *val
= sign_extend32(
175 be16_to_cpu(buffer
[chan
->scan_index
]) >> 4, 11);
177 case IIO_CHAN_INFO_SCALE
:
178 i
= data
->data_cfg
& MMA8452_DATA_CFG_FS_MASK
;
179 *val
= mma8452_scales
[i
][0];
180 *val2
= mma8452_scales
[i
][1];
181 return IIO_VAL_INT_PLUS_MICRO
;
182 case IIO_CHAN_INFO_SAMP_FREQ
:
183 i
= (data
->ctrl_reg1
& MMA8452_CTRL_DR_MASK
) >>
184 MMA8452_CTRL_DR_SHIFT
;
185 *val
= mma8452_samp_freq
[i
][0];
186 *val2
= mma8452_samp_freq
[i
][1];
187 return IIO_VAL_INT_PLUS_MICRO
;
188 case IIO_CHAN_INFO_CALIBBIAS
:
189 ret
= i2c_smbus_read_byte_data(data
->client
, MMA8452_OFF_X
+
193 *val
= sign_extend32(ret
, 7);
199 static int mma8452_standby(struct mma8452_data
*data
)
201 return i2c_smbus_write_byte_data(data
->client
, MMA8452_CTRL_REG1
,
202 data
->ctrl_reg1
& ~MMA8452_CTRL_ACTIVE
);
205 static int mma8452_active(struct mma8452_data
*data
)
207 return i2c_smbus_write_byte_data(data
->client
, MMA8452_CTRL_REG1
,
211 static int mma8452_change_config(struct mma8452_data
*data
, u8 reg
, u8 val
)
215 mutex_lock(&data
->lock
);
217 /* config can only be changed when in standby */
218 ret
= mma8452_standby(data
);
222 ret
= i2c_smbus_write_byte_data(data
->client
, reg
, val
);
226 ret
= mma8452_active(data
);
232 mutex_unlock(&data
->lock
);
236 static int mma8452_write_raw(struct iio_dev
*indio_dev
,
237 struct iio_chan_spec
const *chan
,
238 int val
, int val2
, long mask
)
240 struct mma8452_data
*data
= iio_priv(indio_dev
);
243 if (iio_buffer_enabled(indio_dev
))
247 case IIO_CHAN_INFO_SAMP_FREQ
:
248 i
= mma8452_get_samp_freq_index(data
, val
, val2
);
252 data
->ctrl_reg1
&= ~MMA8452_CTRL_DR_MASK
;
253 data
->ctrl_reg1
|= i
<< MMA8452_CTRL_DR_SHIFT
;
254 return mma8452_change_config(data
, MMA8452_CTRL_REG1
,
256 case IIO_CHAN_INFO_SCALE
:
257 i
= mma8452_get_scale_index(data
, val
, val2
);
260 data
->data_cfg
&= ~MMA8452_DATA_CFG_FS_MASK
;
262 return mma8452_change_config(data
, MMA8452_DATA_CFG
,
264 case IIO_CHAN_INFO_CALIBBIAS
:
265 if (val
< -128 || val
> 127)
267 return mma8452_change_config(data
, MMA8452_OFF_X
+
268 chan
->scan_index
, val
);
274 static irqreturn_t
mma8452_trigger_handler(int irq
, void *p
)
276 struct iio_poll_func
*pf
= p
;
277 struct iio_dev
*indio_dev
= pf
->indio_dev
;
278 struct mma8452_data
*data
= iio_priv(indio_dev
);
279 u8 buffer
[16]; /* 3 16-bit channels + padding + ts */
282 ret
= mma8452_read(data
, (__be16
*) buffer
);
286 iio_push_to_buffers_with_timestamp(indio_dev
, buffer
,
290 iio_trigger_notify_done(indio_dev
->trig
);
294 #define MMA8452_CHANNEL(axis, idx) { \
297 .channel2 = IIO_MOD_##axis, \
298 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
299 BIT(IIO_CHAN_INFO_CALIBBIAS), \
300 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
301 BIT(IIO_CHAN_INFO_SCALE), \
308 .endianness = IIO_BE, \
312 static const struct iio_chan_spec mma8452_channels
[] = {
313 MMA8452_CHANNEL(X
, 0),
314 MMA8452_CHANNEL(Y
, 1),
315 MMA8452_CHANNEL(Z
, 2),
316 IIO_CHAN_SOFT_TIMESTAMP(3),
319 static struct attribute
*mma8452_attributes
[] = {
320 &iio_dev_attr_sampling_frequency_available
.dev_attr
.attr
,
321 &iio_dev_attr_in_accel_scale_available
.dev_attr
.attr
,
325 static const struct attribute_group mma8452_group
= {
326 .attrs
= mma8452_attributes
,
329 static const struct iio_info mma8452_info
= {
330 .attrs
= &mma8452_group
,
331 .read_raw
= &mma8452_read_raw
,
332 .write_raw
= &mma8452_write_raw
,
333 .driver_module
= THIS_MODULE
,
336 static const unsigned long mma8452_scan_masks
[] = {0x7, 0};
338 static int mma8452_probe(struct i2c_client
*client
,
339 const struct i2c_device_id
*id
)
341 struct mma8452_data
*data
;
342 struct iio_dev
*indio_dev
;
345 ret
= i2c_smbus_read_byte_data(client
, MMA8452_WHO_AM_I
);
348 if (ret
!= MMA8452_DEVICE_ID
)
351 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*data
));
355 data
= iio_priv(indio_dev
);
356 data
->client
= client
;
357 mutex_init(&data
->lock
);
359 i2c_set_clientdata(client
, indio_dev
);
360 indio_dev
->info
= &mma8452_info
;
361 indio_dev
->name
= id
->name
;
362 indio_dev
->dev
.parent
= &client
->dev
;
363 indio_dev
->modes
= INDIO_DIRECT_MODE
;
364 indio_dev
->channels
= mma8452_channels
;
365 indio_dev
->num_channels
= ARRAY_SIZE(mma8452_channels
);
366 indio_dev
->available_scan_masks
= mma8452_scan_masks
;
368 data
->ctrl_reg1
= MMA8452_CTRL_ACTIVE
|
369 (MMA8452_CTRL_DR_DEFAULT
<< MMA8452_CTRL_DR_SHIFT
);
370 ret
= i2c_smbus_write_byte_data(client
, MMA8452_CTRL_REG1
,
375 data
->data_cfg
= MMA8452_DATA_CFG_FS_2G
;
376 ret
= i2c_smbus_write_byte_data(client
, MMA8452_DATA_CFG
,
381 ret
= iio_triggered_buffer_setup(indio_dev
, NULL
,
382 mma8452_trigger_handler
, NULL
);
386 ret
= iio_device_register(indio_dev
);
392 iio_triggered_buffer_cleanup(indio_dev
);
396 static int mma8452_remove(struct i2c_client
*client
)
398 struct iio_dev
*indio_dev
= i2c_get_clientdata(client
);
400 iio_device_unregister(indio_dev
);
401 iio_triggered_buffer_cleanup(indio_dev
);
402 mma8452_standby(iio_priv(indio_dev
));
407 #ifdef CONFIG_PM_SLEEP
408 static int mma8452_suspend(struct device
*dev
)
410 return mma8452_standby(iio_priv(i2c_get_clientdata(
411 to_i2c_client(dev
))));
414 static int mma8452_resume(struct device
*dev
)
416 return mma8452_active(iio_priv(i2c_get_clientdata(
417 to_i2c_client(dev
))));
420 static SIMPLE_DEV_PM_OPS(mma8452_pm_ops
, mma8452_suspend
, mma8452_resume
);
421 #define MMA8452_PM_OPS (&mma8452_pm_ops)
423 #define MMA8452_PM_OPS NULL
426 static const struct i2c_device_id mma8452_id
[] = {
430 MODULE_DEVICE_TABLE(i2c
, mma8452_id
);
432 static const struct of_device_id mma8452_dt_ids
[] = {
433 { .compatible
= "fsl,mma8452" },
437 static struct i2c_driver mma8452_driver
= {
440 .of_match_table
= of_match_ptr(mma8452_dt_ids
),
441 .pm
= MMA8452_PM_OPS
,
443 .probe
= mma8452_probe
,
444 .remove
= mma8452_remove
,
445 .id_table
= mma8452_id
,
447 module_i2c_driver(mma8452_driver
);
449 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
450 MODULE_DESCRIPTION("Freescale MMA8452 accelerometer driver");
451 MODULE_LICENSE("GPL");