brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · 9922868 Raw
187 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * IIO driver for the MiraMEMS DA217 and DA280 3-axis accelerometer and4 * IIO driver for the MiraMEMS DA226 2-axis accelerometer5 *6 * Copyright (c) 2016 Hans de Goede <hdegoede@redhat.com>7 */8 9#include <linux/module.h>10#include <linux/i2c.h>11#include <linux/acpi.h>12#include <linux/iio/iio.h>13#include <linux/iio/sysfs.h>14#include <linux/byteorder/generic.h>15 16#define DA280_REG_CHIP_ID		0x0117#define DA280_REG_ACC_X_LSB		0x0218#define DA280_REG_ACC_Y_LSB		0x0419#define DA280_REG_ACC_Z_LSB		0x0620#define DA280_REG_MODE_BW		0x1121 22#define DA280_CHIP_ID			0x1323#define DA280_MODE_ENABLE		0x1e24#define DA280_MODE_DISABLE		0x9e25 26/*27 * a value of + or -4096 corresponds to + or - 1G28 * scale = 9.81 / 4096 = 0.00239501929 */30 31static const int da280_nscale = 2395019;32 33#define DA280_CHANNEL(reg, axis) {	\34	.type = IIO_ACCEL,	\35	.address = reg,	\36	.modified = 1,	\37	.channel2 = IIO_MOD_##axis,	\38	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\39	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\40}41 42static const struct iio_chan_spec da280_channels[] = {43	DA280_CHANNEL(DA280_REG_ACC_X_LSB, X),44	DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y),45	DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),46};47 48struct da280_match_data {49	const char *name;50	int num_channels;51};52 53struct da280_data {54	struct i2c_client *client;55};56 57static int da280_enable(struct i2c_client *client, bool enable)58{59	u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE;60 61	return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data);62}63 64static int da280_read_raw(struct iio_dev *indio_dev,65				struct iio_chan_spec const *chan,66				int *val, int *val2, long mask)67{68	struct da280_data *data = iio_priv(indio_dev);69	int ret;70 71	switch (mask) {72	case IIO_CHAN_INFO_RAW:73		ret = i2c_smbus_read_word_data(data->client, chan->address);74		if (ret < 0)75			return ret;76		/*77		 * Values are 14 bits, stored as 16 bits with the 278		 * least significant bits always 0.79		 */80		*val = (short)ret >> 2;81		return IIO_VAL_INT;82	case IIO_CHAN_INFO_SCALE:83		*val = 0;84		*val2 = da280_nscale;85		return IIO_VAL_INT_PLUS_NANO;86	default:87		return -EINVAL;88	}89}90 91static const struct iio_info da280_info = {92	.read_raw	= da280_read_raw,93};94 95static void da280_disable(void *client)96{97	da280_enable(client, false);98}99 100static int da280_probe(struct i2c_client *client)101{102	const struct da280_match_data *match_data;103	struct iio_dev *indio_dev;104	struct da280_data *data;105	int ret;106 107	ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);108	if (ret != DA280_CHIP_ID)109		return (ret < 0) ? ret : -ENODEV;110 111	match_data = i2c_get_match_data(client);112	if (!match_data) {113		dev_err(&client->dev, "Error match-data not set\n");114		return -EINVAL;115	}116 117	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));118	if (!indio_dev)119		return -ENOMEM;120 121	data = iio_priv(indio_dev);122	data->client = client;123 124	indio_dev->info = &da280_info;125	indio_dev->modes = INDIO_DIRECT_MODE;126	indio_dev->channels = da280_channels;127	indio_dev->num_channels = match_data->num_channels;128	indio_dev->name = match_data->name;129 130	ret = da280_enable(client, true);131	if (ret < 0)132		return ret;133 134	ret = devm_add_action_or_reset(&client->dev, da280_disable, client);135	if (ret)136		return ret;137 138	return devm_iio_device_register(&client->dev, indio_dev);139}140 141static int da280_suspend(struct device *dev)142{143	return da280_enable(to_i2c_client(dev), false);144}145 146static int da280_resume(struct device *dev)147{148	return da280_enable(to_i2c_client(dev), true);149}150 151static DEFINE_SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);152 153static const struct da280_match_data da217_match_data = { "da217", 3 };154static const struct da280_match_data da226_match_data = { "da226", 2 };155static const struct da280_match_data da280_match_data = { "da280", 3 };156 157static const struct acpi_device_id da280_acpi_match[] = {158	{ "NSA2513", (kernel_ulong_t)&da217_match_data },159	{ "MIRAACC", (kernel_ulong_t)&da280_match_data },160	{}161};162MODULE_DEVICE_TABLE(acpi, da280_acpi_match);163 164static const struct i2c_device_id da280_i2c_id[] = {165	{ "da217", (kernel_ulong_t)&da217_match_data },166	{ "da226", (kernel_ulong_t)&da226_match_data },167	{ "da280", (kernel_ulong_t)&da280_match_data },168	{}169};170MODULE_DEVICE_TABLE(i2c, da280_i2c_id);171 172static struct i2c_driver da280_driver = {173	.driver = {174		.name = "da280",175		.acpi_match_table = da280_acpi_match,176		.pm = pm_sleep_ptr(&da280_pm_ops),177	},178	.probe		= da280_probe,179	.id_table	= da280_i2c_id,180};181 182module_i2c_driver(da280_driver);183 184MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");185MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver");186MODULE_LICENSE("GPL v2");187