2 * MXC6255 - MEMSIC orientation sensing accelerometer
4 * Copyright (c) 2015, Intel Corporation.
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 * IIO driver for MXC6255 (7-bit I2C slave address 0x15).
13 #include <linux/module.h>
14 #include <linux/i2c.h>
15 #include <linux/init.h>
16 #include <linux/iio/iio.h>
17 #include <linux/delay.h>
18 #include <linux/acpi.h>
19 #include <linux/regmap.h>
20 #include <linux/iio/sysfs.h>
22 #define MXC6255_DRV_NAME "mxc6255"
23 #define MXC6255_REGMAP_NAME "mxc6255_regmap"
25 #define MXC6255_REG_XOUT 0x00
26 #define MXC6255_REG_YOUT 0x01
27 #define MXC6255_REG_CHIP_ID 0x08
29 #define MXC6255_CHIP_ID 0x05
32 * MXC6255 has only one measurement range: +/- 2G.
33 * The acceleration output is an 8-bit value.
35 * Scale is calculated as follows:
36 * (2 + 2) * 9.80665 / (2^8 - 1) = 0.153829
38 * Scale value for +/- 2G measurement range
40 #define MXC6255_SCALE 153829
48 struct i2c_client
*client
;
49 struct regmap
*regmap
;
52 static int mxc6255_read_raw(struct iio_dev
*indio_dev
,
53 struct iio_chan_spec
const *chan
,
54 int *val
, int *val2
, long mask
)
56 struct mxc6255_data
*data
= iio_priv(indio_dev
);
61 case IIO_CHAN_INFO_RAW
:
62 ret
= regmap_read(data
->regmap
, chan
->address
, ®
);
64 dev_err(&data
->client
->dev
,
65 "Error reading reg %lu\n", chan
->address
);
69 *val
= sign_extend32(reg
, 7);
71 case IIO_CHAN_INFO_SCALE
:
73 *val2
= MXC6255_SCALE
;
74 return IIO_VAL_INT_PLUS_MICRO
;
80 static const struct iio_info mxc6255_info
= {
81 .read_raw
= mxc6255_read_raw
,
84 #define MXC6255_CHANNEL(_axis, reg) { \
87 .channel2 = IIO_MOD_##_axis, \
89 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
90 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
93 static const struct iio_chan_spec mxc6255_channels
[] = {
94 MXC6255_CHANNEL(X
, MXC6255_REG_XOUT
),
95 MXC6255_CHANNEL(Y
, MXC6255_REG_YOUT
),
98 static bool mxc6255_is_readable_reg(struct device
*dev
, unsigned int reg
)
101 case MXC6255_REG_XOUT
:
102 case MXC6255_REG_YOUT
:
103 case MXC6255_REG_CHIP_ID
:
110 static const struct regmap_config mxc6255_regmap_config
= {
111 .name
= MXC6255_REGMAP_NAME
,
116 .readable_reg
= mxc6255_is_readable_reg
,
119 static int mxc6255_probe(struct i2c_client
*client
,
120 const struct i2c_device_id
*id
)
122 struct mxc6255_data
*data
;
123 struct iio_dev
*indio_dev
;
124 struct regmap
*regmap
;
125 unsigned int chip_id
;
128 indio_dev
= devm_iio_device_alloc(&client
->dev
, sizeof(*data
));
132 regmap
= devm_regmap_init_i2c(client
, &mxc6255_regmap_config
);
133 if (IS_ERR(regmap
)) {
134 dev_err(&client
->dev
, "Error initializing regmap\n");
135 return PTR_ERR(regmap
);
138 data
= iio_priv(indio_dev
);
139 i2c_set_clientdata(client
, indio_dev
);
140 data
->client
= client
;
141 data
->regmap
= regmap
;
143 indio_dev
->name
= MXC6255_DRV_NAME
;
144 indio_dev
->dev
.parent
= &client
->dev
;
145 indio_dev
->channels
= mxc6255_channels
;
146 indio_dev
->num_channels
= ARRAY_SIZE(mxc6255_channels
);
147 indio_dev
->modes
= INDIO_DIRECT_MODE
;
148 indio_dev
->info
= &mxc6255_info
;
150 ret
= regmap_read(data
->regmap
, MXC6255_REG_CHIP_ID
, &chip_id
);
152 dev_err(&client
->dev
, "Error reading chip id %d\n", ret
);
156 if ((chip_id
& 0x1f) != MXC6255_CHIP_ID
) {
157 dev_err(&client
->dev
, "Invalid chip id %x\n", chip_id
);
161 dev_dbg(&client
->dev
, "Chip id %x\n", chip_id
);
163 ret
= devm_iio_device_register(&client
->dev
, indio_dev
);
165 dev_err(&client
->dev
, "Could not register IIO device\n");
172 static const struct acpi_device_id mxc6255_acpi_match
[] = {
177 MODULE_DEVICE_TABLE(acpi
, mxc6255_acpi_match
);
179 static const struct i2c_device_id mxc6255_id
[] = {
184 MODULE_DEVICE_TABLE(i2c
, mxc6255_id
);
186 static struct i2c_driver mxc6255_driver
= {
188 .name
= MXC6255_DRV_NAME
,
189 .acpi_match_table
= ACPI_PTR(mxc6255_acpi_match
),
191 .probe
= mxc6255_probe
,
192 .id_table
= mxc6255_id
,
195 module_i2c_driver(mxc6255_driver
);
197 MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>");
198 MODULE_DESCRIPTION("MEMSIC MXC6255 orientation sensing accelerometer driver");
199 MODULE_LICENSE("GPL v2");