0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/i2c.h>
0012 #include <linux/init.h>
0013 #include <linux/iio/iio.h>
0014 #include <linux/delay.h>
0015 #include <linux/acpi.h>
0016 #include <linux/regmap.h>
0017 #include <linux/iio/sysfs.h>
0018
0019 #define MXC6255_DRV_NAME "mxc6255"
0020 #define MXC6255_REGMAP_NAME "mxc6255_regmap"
0021
0022 #define MXC6255_REG_XOUT 0x00
0023 #define MXC6255_REG_YOUT 0x01
0024 #define MXC6255_REG_CHIP_ID 0x08
0025
0026 #define MXC6255_CHIP_ID 0x05
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #define MXC6255_SCALE 153829
0038
0039 enum mxc6255_axis {
0040 AXIS_X,
0041 AXIS_Y,
0042 };
0043
0044 struct mxc6255_data {
0045 struct i2c_client *client;
0046 struct regmap *regmap;
0047 };
0048
0049 static int mxc6255_read_raw(struct iio_dev *indio_dev,
0050 struct iio_chan_spec const *chan,
0051 int *val, int *val2, long mask)
0052 {
0053 struct mxc6255_data *data = iio_priv(indio_dev);
0054 unsigned int reg;
0055 int ret;
0056
0057 switch (mask) {
0058 case IIO_CHAN_INFO_RAW:
0059 ret = regmap_read(data->regmap, chan->address, ®);
0060 if (ret < 0) {
0061 dev_err(&data->client->dev,
0062 "Error reading reg %lu\n", chan->address);
0063 return ret;
0064 }
0065
0066 *val = sign_extend32(reg, 7);
0067 return IIO_VAL_INT;
0068 case IIO_CHAN_INFO_SCALE:
0069 *val = 0;
0070 *val2 = MXC6255_SCALE;
0071 return IIO_VAL_INT_PLUS_MICRO;
0072 default:
0073 return -EINVAL;
0074 }
0075 }
0076
0077 static const struct iio_info mxc6255_info = {
0078 .read_raw = mxc6255_read_raw,
0079 };
0080
0081 #define MXC6255_CHANNEL(_axis, reg) { \
0082 .type = IIO_ACCEL, \
0083 .modified = 1, \
0084 .channel2 = IIO_MOD_##_axis, \
0085 .address = reg, \
0086 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0087 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
0088 }
0089
0090 static const struct iio_chan_spec mxc6255_channels[] = {
0091 MXC6255_CHANNEL(X, MXC6255_REG_XOUT),
0092 MXC6255_CHANNEL(Y, MXC6255_REG_YOUT),
0093 };
0094
0095 static bool mxc6255_is_readable_reg(struct device *dev, unsigned int reg)
0096 {
0097 switch (reg) {
0098 case MXC6255_REG_XOUT:
0099 case MXC6255_REG_YOUT:
0100 case MXC6255_REG_CHIP_ID:
0101 return true;
0102 default:
0103 return false;
0104 }
0105 }
0106
0107 static const struct regmap_config mxc6255_regmap_config = {
0108 .name = MXC6255_REGMAP_NAME,
0109
0110 .reg_bits = 8,
0111 .val_bits = 8,
0112
0113 .readable_reg = mxc6255_is_readable_reg,
0114 };
0115
0116 static int mxc6255_probe(struct i2c_client *client,
0117 const struct i2c_device_id *id)
0118 {
0119 struct mxc6255_data *data;
0120 struct iio_dev *indio_dev;
0121 struct regmap *regmap;
0122 unsigned int chip_id;
0123 int ret;
0124
0125 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0126 if (!indio_dev)
0127 return -ENOMEM;
0128
0129 regmap = devm_regmap_init_i2c(client, &mxc6255_regmap_config);
0130 if (IS_ERR(regmap)) {
0131 dev_err(&client->dev, "Error initializing regmap\n");
0132 return PTR_ERR(regmap);
0133 }
0134
0135 data = iio_priv(indio_dev);
0136 i2c_set_clientdata(client, indio_dev);
0137 data->client = client;
0138 data->regmap = regmap;
0139
0140 indio_dev->name = MXC6255_DRV_NAME;
0141 indio_dev->channels = mxc6255_channels;
0142 indio_dev->num_channels = ARRAY_SIZE(mxc6255_channels);
0143 indio_dev->modes = INDIO_DIRECT_MODE;
0144 indio_dev->info = &mxc6255_info;
0145
0146 ret = regmap_read(data->regmap, MXC6255_REG_CHIP_ID, &chip_id);
0147 if (ret < 0) {
0148 dev_err(&client->dev, "Error reading chip id %d\n", ret);
0149 return ret;
0150 }
0151
0152 if ((chip_id & 0x1f) != MXC6255_CHIP_ID) {
0153 dev_err(&client->dev, "Invalid chip id %x\n", chip_id);
0154 return -ENODEV;
0155 }
0156
0157 dev_dbg(&client->dev, "Chip id %x\n", chip_id);
0158
0159 ret = devm_iio_device_register(&client->dev, indio_dev);
0160 if (ret < 0) {
0161 dev_err(&client->dev, "Could not register IIO device\n");
0162 return ret;
0163 }
0164
0165 return 0;
0166 }
0167
0168 static const struct acpi_device_id mxc6255_acpi_match[] = {
0169 {"MXC6225", 0},
0170 {"MXC6255", 0},
0171 { }
0172 };
0173 MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match);
0174
0175 static const struct i2c_device_id mxc6255_id[] = {
0176 {"mxc6225", 0},
0177 {"mxc6255", 0},
0178 { }
0179 };
0180 MODULE_DEVICE_TABLE(i2c, mxc6255_id);
0181
0182 static struct i2c_driver mxc6255_driver = {
0183 .driver = {
0184 .name = MXC6255_DRV_NAME,
0185 .acpi_match_table = ACPI_PTR(mxc6255_acpi_match),
0186 },
0187 .probe = mxc6255_probe,
0188 .id_table = mxc6255_id,
0189 };
0190
0191 module_i2c_driver(mxc6255_driver);
0192
0193 MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>");
0194 MODULE_DESCRIPTION("MEMSIC MXC6255 orientation sensing accelerometer driver");
0195 MODULE_LICENSE("GPL v2");