brintos

brintos / linux-shallow public Read only

0
0
Text · 14.0 KiB · fc54a2a Raw
609 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * 3-axis accelerometer driver for MXC4005XC Memsic sensor4 *5 * Copyright (c) 2014, Intel Corporation.6 */7 8#include <linux/delay.h>9#include <linux/module.h>10#include <linux/i2c.h>11#include <linux/iio/iio.h>12#include <linux/mod_devicetable.h>13#include <linux/regmap.h>14#include <linux/iio/sysfs.h>15#include <linux/iio/trigger.h>16#include <linux/iio/buffer.h>17#include <linux/iio/triggered_buffer.h>18#include <linux/iio/trigger_consumer.h>19 20#define MXC4005_DRV_NAME		"mxc4005"21#define MXC4005_IRQ_NAME		"mxc4005_event"22#define MXC4005_REGMAP_NAME		"mxc4005_regmap"23 24#define MXC4005_REG_XOUT_UPPER		0x0325#define MXC4005_REG_XOUT_LOWER		0x0426#define MXC4005_REG_YOUT_UPPER		0x0527#define MXC4005_REG_YOUT_LOWER		0x0628#define MXC4005_REG_ZOUT_UPPER		0x0729#define MXC4005_REG_ZOUT_LOWER		0x0830 31#define MXC4005_REG_INT_MASK0		0x0A32 33#define MXC4005_REG_INT_MASK1		0x0B34#define MXC4005_REG_INT_MASK1_BIT_DRDYE	0x0135 36#define MXC4005_REG_INT_CLR0		0x0037 38#define MXC4005_REG_INT_CLR1		0x0139#define MXC4005_REG_INT_CLR1_BIT_DRDYC	0x0140#define MXC4005_REG_INT_CLR1_SW_RST	0x1041 42#define MXC4005_REG_CONTROL		0x0D43#define MXC4005_REG_CONTROL_MASK_FSR	GENMASK(6, 5)44#define MXC4005_CONTROL_FSR_SHIFT	545 46#define MXC4005_REG_DEVICE_ID		0x0E47 48/* Datasheet does not specify a reset time, this is a conservative guess */49#define MXC4005_RESET_TIME_US		200050 51enum mxc4005_axis {52	AXIS_X,53	AXIS_Y,54	AXIS_Z,55};56 57enum mxc4005_range {58	MXC4005_RANGE_2G,59	MXC4005_RANGE_4G,60	MXC4005_RANGE_8G,61};62 63struct mxc4005_data {64	struct device *dev;65	struct mutex mutex;66	struct regmap *regmap;67	struct iio_trigger *dready_trig;68	struct iio_mount_matrix orientation;69	/* Ensure timestamp is naturally aligned */70	struct {71		__be16 chans[3];72		s64 timestamp __aligned(8);73	} scan;74	bool trigger_enabled;75	unsigned int control;76	unsigned int int_mask1;77};78 79/*80 * MXC4005 can operate in the following ranges:81 * +/- 2G, 4G, 8G (the default +/-2G)82 *83 * (2 + 2) * 9.81 / (2^12 - 1) = 0.00958284 * (4 + 4) * 9.81 / (2^12 - 1) = 0.01916485 * (8 + 8) * 9.81 / (2^12 - 1) = 0.03832986 */87static const struct {88	u8 range;89	int scale;90} mxc4005_scale_table[] = {91	{MXC4005_RANGE_2G, 9582},92	{MXC4005_RANGE_4G, 19164},93	{MXC4005_RANGE_8G, 38329},94};95 96 97static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019164 0.038329");98 99static struct attribute *mxc4005_attributes[] = {100	&iio_const_attr_in_accel_scale_available.dev_attr.attr,101	NULL,102};103 104static const struct attribute_group mxc4005_attrs_group = {105	.attrs = mxc4005_attributes,106};107 108static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg)109{110	switch (reg) {111	case MXC4005_REG_XOUT_UPPER:112	case MXC4005_REG_XOUT_LOWER:113	case MXC4005_REG_YOUT_UPPER:114	case MXC4005_REG_YOUT_LOWER:115	case MXC4005_REG_ZOUT_UPPER:116	case MXC4005_REG_ZOUT_LOWER:117	case MXC4005_REG_DEVICE_ID:118	case MXC4005_REG_CONTROL:119		return true;120	default:121		return false;122	}123}124 125static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg)126{127	switch (reg) {128	case MXC4005_REG_INT_CLR0:129	case MXC4005_REG_INT_CLR1:130	case MXC4005_REG_INT_MASK0:131	case MXC4005_REG_INT_MASK1:132	case MXC4005_REG_CONTROL:133		return true;134	default:135		return false;136	}137}138 139static const struct regmap_config mxc4005_regmap_config = {140	.name = MXC4005_REGMAP_NAME,141 142	.reg_bits = 8,143	.val_bits = 8,144 145	.max_register = MXC4005_REG_DEVICE_ID,146 147	.readable_reg = mxc4005_is_readable_reg,148	.writeable_reg = mxc4005_is_writeable_reg,149};150 151static int mxc4005_read_xyz(struct mxc4005_data *data)152{153	int ret;154 155	ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER,156			       data->scan.chans, sizeof(data->scan.chans));157	if (ret < 0) {158		dev_err(data->dev, "failed to read axes\n");159		return ret;160	}161 162	return 0;163}164 165static int mxc4005_read_axis(struct mxc4005_data *data,166			     unsigned int addr)167{168	__be16 reg;169	int ret;170 171	ret = regmap_bulk_read(data->regmap, addr, &reg, sizeof(reg));172	if (ret < 0) {173		dev_err(data->dev, "failed to read reg %02x\n", addr);174		return ret;175	}176 177	return be16_to_cpu(reg);178}179 180static int mxc4005_read_scale(struct mxc4005_data *data)181{182	unsigned int reg;183	int ret;184	int i;185 186	ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &reg);187	if (ret < 0) {188		dev_err(data->dev, "failed to read reg_control\n");189		return ret;190	}191 192	i = reg >> MXC4005_CONTROL_FSR_SHIFT;193 194	if (i < 0 || i >= ARRAY_SIZE(mxc4005_scale_table))195		return -EINVAL;196 197	return mxc4005_scale_table[i].scale;198}199 200static int mxc4005_set_scale(struct mxc4005_data *data, int val)201{202	unsigned int reg;203	int i;204	int ret;205 206	for (i = 0; i < ARRAY_SIZE(mxc4005_scale_table); i++) {207		if (mxc4005_scale_table[i].scale == val) {208			reg = i << MXC4005_CONTROL_FSR_SHIFT;209			ret = regmap_update_bits(data->regmap,210						 MXC4005_REG_CONTROL,211						 MXC4005_REG_CONTROL_MASK_FSR,212						 reg);213			if (ret < 0)214				dev_err(data->dev,215					"failed to write reg_control\n");216			return ret;217		}218	}219 220	return -EINVAL;221}222 223static int mxc4005_read_raw(struct iio_dev *indio_dev,224			    struct iio_chan_spec const *chan,225			    int *val, int *val2, long mask)226{227	struct mxc4005_data *data = iio_priv(indio_dev);228	int ret;229 230	switch (mask) {231	case IIO_CHAN_INFO_RAW:232		switch (chan->type) {233		case IIO_ACCEL:234			if (iio_buffer_enabled(indio_dev))235				return -EBUSY;236 237			ret = mxc4005_read_axis(data, chan->address);238			if (ret < 0)239				return ret;240			*val = sign_extend32(ret >> chan->scan_type.shift,241					     chan->scan_type.realbits - 1);242			return IIO_VAL_INT;243		default:244			return -EINVAL;245		}246	case IIO_CHAN_INFO_SCALE:247		ret = mxc4005_read_scale(data);248		if (ret < 0)249			return ret;250 251		*val = 0;252		*val2 = ret;253		return IIO_VAL_INT_PLUS_MICRO;254	default:255		return -EINVAL;256	}257}258 259static int mxc4005_write_raw(struct iio_dev *indio_dev,260			     struct iio_chan_spec const *chan,261			     int val, int val2, long mask)262{263	struct mxc4005_data *data = iio_priv(indio_dev);264 265	switch (mask) {266	case IIO_CHAN_INFO_SCALE:267		if (val != 0)268			return -EINVAL;269 270		return mxc4005_set_scale(data, val2);271	default:272		return -EINVAL;273	}274}275 276static const struct iio_mount_matrix *277mxc4005_get_mount_matrix(const struct iio_dev *indio_dev,278			   const struct iio_chan_spec *chan)279{280	struct mxc4005_data *data = iio_priv(indio_dev);281 282	return &data->orientation;283}284 285static const struct iio_chan_spec_ext_info mxc4005_ext_info[] = {286	IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, mxc4005_get_mount_matrix),287	{ }288};289 290static const struct iio_info mxc4005_info = {291	.read_raw	= mxc4005_read_raw,292	.write_raw	= mxc4005_write_raw,293	.attrs		= &mxc4005_attrs_group,294};295 296static const unsigned long mxc4005_scan_masks[] = {297	BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),298	0299};300 301#define MXC4005_CHANNEL(_axis, _addr) {				\302	.type = IIO_ACCEL,					\303	.modified = 1,						\304	.channel2 = IIO_MOD_##_axis,				\305	.address = _addr,					\306	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\307	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\308	.scan_index = AXIS_##_axis,				\309	.scan_type = {						\310		.sign = 's',					\311		.realbits = 12,					\312		.storagebits = 16,				\313		.shift = 4,					\314		.endianness = IIO_BE,				\315	},							\316	.ext_info = mxc4005_ext_info,				\317}318 319static const struct iio_chan_spec mxc4005_channels[] = {320	MXC4005_CHANNEL(X, MXC4005_REG_XOUT_UPPER),321	MXC4005_CHANNEL(Y, MXC4005_REG_YOUT_UPPER),322	MXC4005_CHANNEL(Z, MXC4005_REG_ZOUT_UPPER),323	IIO_CHAN_SOFT_TIMESTAMP(3),324};325 326static irqreturn_t mxc4005_trigger_handler(int irq, void *private)327{328	struct iio_poll_func *pf = private;329	struct iio_dev *indio_dev = pf->indio_dev;330	struct mxc4005_data *data = iio_priv(indio_dev);331	int ret;332 333	ret = mxc4005_read_xyz(data);334	if (ret < 0)335		goto err;336 337	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,338					   pf->timestamp);339 340err:341	iio_trigger_notify_done(indio_dev->trig);342 343	return IRQ_HANDLED;344}345 346static void mxc4005_clr_intr(struct mxc4005_data *data)347{348	int ret;349 350	/* clear interrupt */351	ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,352			   MXC4005_REG_INT_CLR1_BIT_DRDYC);353	if (ret < 0)354		dev_err(data->dev, "failed to write to reg_int_clr1\n");355}356 357static int mxc4005_set_trigger_state(struct iio_trigger *trig,358				     bool state)359{360	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);361	struct mxc4005_data *data = iio_priv(indio_dev);362	unsigned int val;363	int ret;364 365	mutex_lock(&data->mutex);366 367	val = state ? MXC4005_REG_INT_MASK1_BIT_DRDYE : 0;368	ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, val);369	if (ret < 0) {370		mutex_unlock(&data->mutex);371		dev_err(data->dev, "failed to update reg_int_mask1");372		return ret;373	}374 375	data->int_mask1 = val;376	data->trigger_enabled = state;377	mutex_unlock(&data->mutex);378 379	return 0;380}381 382static void mxc4005_trigger_reen(struct iio_trigger *trig)383{384	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);385	struct mxc4005_data *data = iio_priv(indio_dev);386 387	if (!data->dready_trig)388		return;389 390	mxc4005_clr_intr(data);391}392 393static const struct iio_trigger_ops mxc4005_trigger_ops = {394	.set_trigger_state = mxc4005_set_trigger_state,395	.reenable = mxc4005_trigger_reen,396};397 398static int mxc4005_chip_init(struct mxc4005_data *data)399{400	int ret;401	unsigned int reg;402 403	ret = regmap_read(data->regmap, MXC4005_REG_DEVICE_ID, &reg);404	if (ret < 0) {405		dev_err(data->dev, "failed to read chip id\n");406		return ret;407	}408 409	dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);410 411	ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,412			   MXC4005_REG_INT_CLR1_SW_RST);413	if (ret < 0)414		return dev_err_probe(data->dev, ret, "resetting chip\n");415 416	fsleep(MXC4005_RESET_TIME_US);417 418	ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);419	if (ret < 0)420		return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");421 422	ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, 0);423	if (ret < 0)424		return dev_err_probe(data->dev, ret, "writing INT_MASK1\n");425 426	return 0;427}428 429static int mxc4005_probe(struct i2c_client *client)430{431	struct mxc4005_data *data;432	struct iio_dev *indio_dev;433	struct regmap *regmap;434	int ret;435 436	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));437	if (!indio_dev)438		return -ENOMEM;439 440	regmap = devm_regmap_init_i2c(client, &mxc4005_regmap_config);441	if (IS_ERR(regmap)) {442		dev_err(&client->dev, "failed to initialize regmap\n");443		return PTR_ERR(regmap);444	}445 446	data = iio_priv(indio_dev);447	i2c_set_clientdata(client, indio_dev);448	data->dev = &client->dev;449	data->regmap = regmap;450 451	ret = mxc4005_chip_init(data);452	if (ret < 0) {453		dev_err(&client->dev, "failed to initialize chip\n");454		return ret;455	}456 457	mutex_init(&data->mutex);458 459	if (!iio_read_acpi_mount_matrix(&client->dev, &data->orientation, "ROTM")) {460		ret = iio_read_mount_matrix(&client->dev, &data->orientation);461		if (ret)462			return ret;463	}464 465	indio_dev->channels = mxc4005_channels;466	indio_dev->num_channels = ARRAY_SIZE(mxc4005_channels);467	indio_dev->available_scan_masks = mxc4005_scan_masks;468	indio_dev->name = MXC4005_DRV_NAME;469	indio_dev->modes = INDIO_DIRECT_MODE;470	indio_dev->info = &mxc4005_info;471 472	ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,473					 iio_pollfunc_store_time,474					 mxc4005_trigger_handler,475					 NULL);476	if (ret < 0) {477		dev_err(&client->dev,478			"failed to setup iio triggered buffer\n");479		return ret;480	}481 482	if (client->irq > 0) {483		data->dready_trig = devm_iio_trigger_alloc(&client->dev,484							   "%s-dev%d",485							   indio_dev->name,486							   iio_device_id(indio_dev));487		if (!data->dready_trig)488			return -ENOMEM;489 490		ret = devm_request_threaded_irq(&client->dev, client->irq,491						iio_trigger_generic_data_rdy_poll,492						NULL,493						IRQF_TRIGGER_FALLING |494						IRQF_ONESHOT,495						MXC4005_IRQ_NAME,496						data->dready_trig);497		if (ret) {498			dev_err(&client->dev,499				"failed to init threaded irq\n");500			return ret;501		}502 503		data->dready_trig->ops = &mxc4005_trigger_ops;504		iio_trigger_set_drvdata(data->dready_trig, indio_dev);505		ret = devm_iio_trigger_register(&client->dev,506						data->dready_trig);507		if (ret) {508			dev_err(&client->dev,509				"failed to register trigger\n");510			return ret;511		}512 513		indio_dev->trig = iio_trigger_get(data->dready_trig);514	}515 516	return devm_iio_device_register(&client->dev, indio_dev);517}518 519static int mxc4005_suspend(struct device *dev)520{521	struct iio_dev *indio_dev = dev_get_drvdata(dev);522	struct mxc4005_data *data = iio_priv(indio_dev);523	int ret;524 525	/* Save control to restore it on resume */526	ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);527	if (ret < 0)528		dev_err(data->dev, "failed to read reg_control\n");529 530	return ret;531}532 533static int mxc4005_resume(struct device *dev)534{535	struct iio_dev *indio_dev = dev_get_drvdata(dev);536	struct mxc4005_data *data = iio_priv(indio_dev);537	int ret;538 539	ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,540			   MXC4005_REG_INT_CLR1_SW_RST);541	if (ret) {542		dev_err(data->dev, "failed to reset chip: %d\n", ret);543		return ret;544	}545 546	fsleep(MXC4005_RESET_TIME_US);547 548	ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);549	if (ret) {550		dev_err(data->dev, "failed to restore control register\n");551		return ret;552	}553 554	ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);555	if (ret) {556		dev_err(data->dev, "failed to restore interrupt 0 mask\n");557		return ret;558	}559 560	ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);561	if (ret) {562		dev_err(data->dev, "failed to restore interrupt 1 mask\n");563		return ret;564	}565 566	return 0;567}568 569static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);570 571static const struct acpi_device_id mxc4005_acpi_match[] = {572	{"MXC4005",	0},573	{"MXC6655",	0},574	{"MDA6655",	0},575	{ },576};577MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);578 579static const struct of_device_id mxc4005_of_match[] = {580	{ .compatible = "memsic,mxc4005", },581	{ .compatible = "memsic,mxc6655", },582	{ },583};584MODULE_DEVICE_TABLE(of, mxc4005_of_match);585 586static const struct i2c_device_id mxc4005_id[] = {587	{ "mxc4005" },588	{ "mxc6655" },589	{ }590};591MODULE_DEVICE_TABLE(i2c, mxc4005_id);592 593static struct i2c_driver mxc4005_driver = {594	.driver = {595		.name = MXC4005_DRV_NAME,596		.acpi_match_table = mxc4005_acpi_match,597		.of_match_table = mxc4005_of_match,598		.pm = pm_sleep_ptr(&mxc4005_pm_ops),599	},600	.probe		= mxc4005_probe,601	.id_table	= mxc4005_id,602};603 604module_i2c_driver(mxc4005_driver);605 606MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>");607MODULE_LICENSE("GPL v2");608MODULE_DESCRIPTION("MXC4005 3-axis accelerometer driver");609