brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · a8abda7 Raw
195 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * MXC6255 - MEMSIC orientation sensing accelerometer4 *5 * Copyright (c) 2015, Intel Corporation.6 *7 * IIO driver for MXC6255 (7-bit I2C slave address 0x15).8 */9 10#include <linux/module.h>11#include <linux/i2c.h>12#include <linux/init.h>13#include <linux/iio/iio.h>14#include <linux/delay.h>15#include <linux/mod_devicetable.h>16#include <linux/regmap.h>17#include <linux/iio/sysfs.h>18 19#define MXC6255_DRV_NAME		"mxc6255"20#define MXC6255_REGMAP_NAME		"mxc6255_regmap"21 22#define MXC6255_REG_XOUT		0x0023#define MXC6255_REG_YOUT		0x0124#define MXC6255_REG_CHIP_ID		0x0825 26#define MXC6255_CHIP_ID			0x0527 28/*29 * MXC6255 has only one measurement range: +/- 2G.30 * The acceleration output is an 8-bit value.31 *32 * Scale is calculated as follows:33 * (2 + 2) * 9.80665 / (2^8 - 1) = 0.15382934 *35 * Scale value for +/- 2G measurement range36 */37#define MXC6255_SCALE			15382938 39enum mxc6255_axis {40	AXIS_X,41	AXIS_Y,42};43 44struct mxc6255_data {45	struct i2c_client *client;46	struct regmap *regmap;47};48 49static int mxc6255_read_raw(struct iio_dev *indio_dev,50			    struct iio_chan_spec const *chan,51			    int *val, int *val2, long mask)52{53	struct mxc6255_data *data = iio_priv(indio_dev);54	unsigned int reg;55	int ret;56 57	switch (mask) {58	case IIO_CHAN_INFO_RAW:59		ret = regmap_read(data->regmap, chan->address, &reg);60		if (ret < 0) {61			dev_err(&data->client->dev,62				"Error reading reg %lu\n", chan->address);63			return ret;64		}65 66		*val = sign_extend32(reg, 7);67		return IIO_VAL_INT;68	case IIO_CHAN_INFO_SCALE:69		*val = 0;70		*val2 = MXC6255_SCALE;71		return IIO_VAL_INT_PLUS_MICRO;72	default:73		return -EINVAL;74	}75}76 77static const struct iio_info mxc6255_info = {78	.read_raw	= mxc6255_read_raw,79};80 81#define MXC6255_CHANNEL(_axis, reg) {				\82	.type = IIO_ACCEL,					\83	.modified = 1,						\84	.channel2 = IIO_MOD_##_axis,				\85	.address = reg,						\86	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\87	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\88}89 90static const struct iio_chan_spec mxc6255_channels[] = {91	MXC6255_CHANNEL(X, MXC6255_REG_XOUT),92	MXC6255_CHANNEL(Y, MXC6255_REG_YOUT),93};94 95static bool mxc6255_is_readable_reg(struct device *dev, unsigned int reg)96{97	switch (reg) {98	case MXC6255_REG_XOUT:99	case MXC6255_REG_YOUT:100	case MXC6255_REG_CHIP_ID:101		return true;102	default:103		return false;104	}105}106 107static const struct regmap_config mxc6255_regmap_config = {108	.name = MXC6255_REGMAP_NAME,109 110	.reg_bits = 8,111	.val_bits = 8,112 113	.readable_reg = mxc6255_is_readable_reg,114};115 116static int mxc6255_probe(struct i2c_client *client)117{118	struct mxc6255_data *data;119	struct iio_dev *indio_dev;120	struct regmap *regmap;121	unsigned int chip_id;122	int ret;123 124	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));125	if (!indio_dev)126		return -ENOMEM;127 128	regmap = devm_regmap_init_i2c(client, &mxc6255_regmap_config);129	if (IS_ERR(regmap)) {130		dev_err(&client->dev, "Error initializing regmap\n");131		return PTR_ERR(regmap);132	}133 134	data = iio_priv(indio_dev);135	i2c_set_clientdata(client, indio_dev);136	data->client = client;137	data->regmap = regmap;138 139	indio_dev->name = MXC6255_DRV_NAME;140	indio_dev->channels = mxc6255_channels;141	indio_dev->num_channels = ARRAY_SIZE(mxc6255_channels);142	indio_dev->modes = INDIO_DIRECT_MODE;143	indio_dev->info = &mxc6255_info;144 145	ret = regmap_read(data->regmap, MXC6255_REG_CHIP_ID, &chip_id);146	if (ret < 0) {147		dev_err(&client->dev, "Error reading chip id %d\n", ret);148		return ret;149	}150 151	if ((chip_id & 0x1f) != MXC6255_CHIP_ID) {152		dev_err(&client->dev, "Invalid chip id %x\n", chip_id);153		return -ENODEV;154	}155 156	dev_dbg(&client->dev, "Chip id %x\n", chip_id);157 158	ret = devm_iio_device_register(&client->dev, indio_dev);159	if (ret < 0) {160		dev_err(&client->dev, "Could not register IIO device\n");161		return ret;162	}163 164	return 0;165}166 167static const struct acpi_device_id mxc6255_acpi_match[] = {168	{"MXC6225",	0},169	{"MXC6255",	0},170	{ }171};172MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match);173 174static const struct i2c_device_id mxc6255_id[] = {175	{ "mxc6225" },176	{ "mxc6255" },177	{ }178};179MODULE_DEVICE_TABLE(i2c, mxc6255_id);180 181static struct i2c_driver mxc6255_driver = {182	.driver = {183		.name = MXC6255_DRV_NAME,184		.acpi_match_table = mxc6255_acpi_match,185	},186	.probe		= mxc6255_probe,187	.id_table	= mxc6255_id,188};189 190module_i2c_driver(mxc6255_driver);191 192MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>");193MODULE_DESCRIPTION("MEMSIC MXC6255 orientation sensing accelerometer driver");194MODULE_LICENSE("GPL v2");195