File Index
Files and directories
Sign in
FILE

mma9551.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/accel/mma9551.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Freescale MMA9551L Intelligent Motion-Sensing Platform driver
  4 * Copyright (c) 2014, Intel Corporation.
  5 */
  6
  7#include <linux/i2c.h>
  8#include <linux/interrupt.h>
  9#include <linux/mod_devicetable.h>
 10#include <linux/module.h>
 11#include <linux/slab.h>
 12#include <linux/delay.h>
 13#include <linux/gpio/consumer.h>
 14#include <linux/iio/iio.h>
 15#include <linux/iio/sysfs.h>
 16#include <linux/iio/events.h>
 17#include <linux/pm_runtime.h>
 18#include "mma9551_core.h"
 19
 20#define MMA9551_GPIO_COUNT		4
 21
 22/* Tilt application (inclination in IIO terms). */
 23#define MMA9551_TILT_XZ_ANG_REG		0x00
 24#define MMA9551_TILT_YZ_ANG_REG		0x01
 25#define MMA9551_TILT_XY_ANG_REG		0x02
 26#define MMA9551_TILT_ANGFLG		BIT(7)
 27#define MMA9551_TILT_QUAD_REG		0x03
 28#define MMA9551_TILT_XY_QUAD_SHIFT	0
 29#define MMA9551_TILT_YZ_QUAD_SHIFT	2
 30#define MMA9551_TILT_XZ_QUAD_SHIFT	4
 31#define MMA9551_TILT_CFG_REG		0x01
 32#define MMA9551_TILT_ANG_THRESH_MASK	GENMASK(3, 0)
 33
 34#define MMA9551_DEFAULT_SAMPLE_RATE	122	/* Hz */
 35
 36/* Tilt events are mapped to the first three GPIO pins. */
 37enum mma9551_tilt_axis {
 38	mma9551_x = 0,
 39	mma9551_y,
 40	mma9551_z,
 41};
 42
 43struct mma9551_data {
 44	struct i2c_client *client;
 45	struct mutex mutex;
 46	bool event_enabled[3];
 47	int irqs[MMA9551_GPIO_COUNT];
 48};
 49
 50static int mma9551_read_incli_chan(struct i2c_client *client,
 51				   const struct iio_chan_spec *chan,
 52				   int *val)
 53{
 54	u8 quad_shift, angle, quadrant;
 55	u16 reg_addr;
 56	int ret;
 57
 58	switch (chan->channel2) {
 59	case IIO_MOD_X:
 60		reg_addr = MMA9551_TILT_YZ_ANG_REG;
 61		quad_shift = MMA9551_TILT_YZ_QUAD_SHIFT;
 62		break;
 63	case IIO_MOD_Y:
 64		reg_addr = MMA9551_TILT_XZ_ANG_REG;
 65		quad_shift = MMA9551_TILT_XZ_QUAD_SHIFT;
 66		break;
 67	case IIO_MOD_Z:
 68		reg_addr = MMA9551_TILT_XY_ANG_REG;
 69		quad_shift = MMA9551_TILT_XY_QUAD_SHIFT;
 70		break;
 71	default:
 72		return -EINVAL;
 73	}
 74
 75	ret = mma9551_set_power_state(client, true);
 76	if (ret < 0)
 77		return ret;
 78
 79	ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
 80				       reg_addr, &angle);
 81	if (ret < 0)
 82		goto out_poweroff;
 83
 84	ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT,
 85				       MMA9551_TILT_QUAD_REG, &quadrant);
 86	if (ret < 0)
 87		goto out_poweroff;
 88
 89	angle &= ~MMA9551_TILT_ANGFLG;
 90	quadrant = (quadrant >> quad_shift) & 0x03;
 91
 92	if (quadrant == 1 || quadrant == 3)
 93		*val = 90 * (quadrant + 1) - angle;
 94	else
 95		*val = angle + 90 * quadrant;
 96
 97	ret = IIO_VAL_INT;
 98
 99out_poweroff:
100	mma9551_set_power_state(client, false);
101	return ret;
102}
103
104static int mma9551_read_raw(struct iio_dev *indio_dev,
105			    struct iio_chan_spec const *chan,
106			    int *val, int *val2, long mask)
107{
108	struct mma9551_data *data = iio_priv(indio_dev);
109	int ret;
110
111	switch (mask) {
112	case IIO_CHAN_INFO_PROCESSED:
113		switch (chan->type) {
114		case IIO_INCLI:
115			mutex_lock(&data->mutex);
116			ret = mma9551_read_incli_chan(data->client, chan, val);
117			mutex_unlock(&data->mutex);
118			return ret;
119		default:
120			return -EINVAL;
121		}
122	case IIO_CHAN_INFO_RAW:
123		switch (chan->type) {
124		case IIO_ACCEL:
125			mutex_lock(&data->mutex);
126			ret = mma9551_read_accel_chan(data->client,
127						      chan, val, val2);
128			mutex_unlock(&data->mutex);
129			return ret;
130		default:
131			return -EINVAL;
132		}
133	case IIO_CHAN_INFO_SCALE:
134		switch (chan->type) {
135		case IIO_ACCEL:
136			return mma9551_read_accel_scale(val, val2);
137		default:
138			return -EINVAL;
139		}
140	default:
141		return -EINVAL;
142	}
143}
144
145static int mma9551_read_event_config(struct iio_dev *indio_dev,
146				     const struct iio_chan_spec *chan,
147				     enum iio_event_type type,
148				     enum iio_event_direction dir)
149{
150	struct mma9551_data *data = iio_priv(indio_dev);
151
152	switch (chan->type) {
153	case IIO_INCLI:
154		/* IIO counts axes from 1, because IIO_NO_MOD is 0. */
155		return data->event_enabled[chan->channel2 - 1];
156	default:
157		return -EINVAL;
158	}
159}
160
161static int mma9551_config_incli_event(struct iio_dev *indio_dev,
162				      enum iio_modifier axis,
163				      bool state)
164{
165	struct mma9551_data *data = iio_priv(indio_dev);
166	enum mma9551_tilt_axis mma_axis;
167	int ret;
168
169	/* IIO counts axes from 1, because IIO_NO_MOD is 0. */
170	mma_axis = axis - 1;
171
172	if (data->event_enabled[mma_axis] == state)
173		return 0;
174
175	if (!state) {
176		ret = mma9551_gpio_config(data->client,
177					  (enum mma9551_gpio_pin)mma_axis,
178					  MMA9551_APPID_NONE, 0, 0);
179		if (ret < 0)
180			return ret;
181
182		ret = mma9551_set_power_state(data->client, false);
183		if (ret < 0)
184			return ret;
185	} else {
186		int bitnum;
187
188		/* Bit 7 of each angle register holds the angle flag. */
189		switch (axis) {
190		case IIO_MOD_X:
191			bitnum = 7 + 8 * MMA9551_TILT_YZ_ANG_REG;
192			break;
193		case IIO_MOD_Y:
194			bitnum = 7 + 8 * MMA9551_TILT_XZ_ANG_REG;
195			break;
196		case IIO_MOD_Z:
197			bitnum = 7 + 8 * MMA9551_TILT_XY_ANG_REG;
198			break;
199		default:
200			return -EINVAL;
201		}
202
203
204		ret = mma9551_set_power_state(data->client, true);
205		if (ret < 0)
206			return ret;
207
208		ret = mma9551_gpio_config(data->client,
209					  (enum mma9551_gpio_pin)mma_axis,
210					  MMA9551_APPID_TILT, bitnum, 0);
211		if (ret < 0) {
212			mma9551_set_power_state(data->client, false);
213			return ret;
214		}
215	}
216
217	data->event_enabled[mma_axis] = state;
218
219	return ret;
220}
221
222static int mma9551_write_event_config(struct iio_dev *indio_dev,
223				      const struct iio_chan_spec *chan,
224				      enum iio_event_type type,
225				      enum iio_event_direction dir,
226				      bool state)
227{
228	struct mma9551_data *data = iio_priv(indio_dev);
229	int ret;
230
231	switch (chan->type) {
232	case IIO_INCLI:
233		mutex_lock(&data->mutex);
234		ret = mma9551_config_incli_event(indio_dev,
235						 chan->channel2, state);
236		mutex_unlock(&data->mutex);
237		return ret;
238	default:
239		return -EINVAL;
240	}
241}
242
243static int mma9551_write_event_value(struct iio_dev *indio_dev,
244				     const struct iio_chan_spec *chan,
245				     enum iio_event_type type,
246				     enum iio_event_direction dir,
247				     enum iio_event_info info,
248				     int val, int val2)
249{
250	struct mma9551_data *data = iio_priv(indio_dev);
251	int ret;
252
253	switch (chan->type) {
254	case IIO_INCLI:
255		if (val2 != 0 || val < 1 || val > 10)
256			return -EINVAL;
257		mutex_lock(&data->mutex);
258		ret = mma9551_update_config_bits(data->client,
259						 MMA9551_APPID_TILT,
260						 MMA9551_TILT_CFG_REG,
261						 MMA9551_TILT_ANG_THRESH_MASK,
262						 val);
263		mutex_unlock(&data->mutex);
264		return ret;
265	default:
266		return -EINVAL;
267	}
268}
269
270static int mma9551_read_event_value(struct iio_dev *indio_dev,
271				    const struct iio_chan_spec *chan,
272				    enum iio_event_type type,
273				    enum iio_event_direction dir,
274				    enum iio_event_info info,
275				    int *val, int *val2)
276{
277	struct mma9551_data *data = iio_priv(indio_dev);
278	int ret;
279	u8 tmp;
280
281	switch (chan->type) {
282	case IIO_INCLI:
283		mutex_lock(&data->mutex);
284		ret = mma9551_read_config_byte(data->client,
285					       MMA9551_APPID_TILT,
286					       MMA9551_TILT_CFG_REG, &tmp);
287		mutex_unlock(&data->mutex);
288		if (ret < 0)
289			return ret;
290		*val = tmp & MMA9551_TILT_ANG_THRESH_MASK;
291		*val2 = 0;
292		return IIO_VAL_INT;
293	default:
294		return -EINVAL;
295	}
296}
297
298static const struct iio_event_spec mma9551_incli_event = {
299	.type = IIO_EV_TYPE_ROC,
300	.dir = IIO_EV_DIR_RISING,
301	.mask_separate = BIT(IIO_EV_INFO_ENABLE),
302	.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
303};
304
305#define MMA9551_INCLI_CHANNEL(axis) {				\
306	.type = IIO_INCLI,					\
307	.modified = 1,						\
308	.channel2 = axis,					\
309	.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),	\
310	.event_spec = &mma9551_incli_event,			\
311	.num_event_specs = 1,					\
312}
313
314static const struct iio_chan_spec mma9551_channels[] = {
315	MMA9551_ACCEL_CHANNEL(IIO_MOD_X),
316	MMA9551_ACCEL_CHANNEL(IIO_MOD_Y),
317	MMA9551_ACCEL_CHANNEL(IIO_MOD_Z),
318
319	MMA9551_INCLI_CHANNEL(IIO_MOD_X),
320	MMA9551_INCLI_CHANNEL(IIO_MOD_Y),
321	MMA9551_INCLI_CHANNEL(IIO_MOD_Z),
322};
323
324static const struct iio_info mma9551_info = {
325	.read_raw = mma9551_read_raw,
326	.read_event_config = mma9551_read_event_config,
327	.write_event_config = mma9551_write_event_config,
328	.read_event_value = mma9551_read_event_value,
329	.write_event_value = mma9551_write_event_value,
330};
331
332static irqreturn_t mma9551_event_handler(int irq, void *private)
333{
334	struct iio_dev *indio_dev = private;
335	struct mma9551_data *data = iio_priv(indio_dev);
336	int i, ret, mma_axis = -1;
337	u16 reg;
338	u8 val;
339
340	mutex_lock(&data->mutex);
341
342	for (i = 0; i < 3; i++)
343		if (irq == data->irqs[i]) {
344			mma_axis = i;
345			break;
346		}
347
348	if (mma_axis == -1) {
349		/* IRQ was triggered on 4th line, which we don't use. */
350		dev_warn(&data->client->dev,
351			 "irq triggered on unused line %d\n", data->irqs[3]);
352		goto out;
353	}
354
355	switch (mma_axis) {
356	case mma9551_x:
357		reg = MMA9551_TILT_YZ_ANG_REG;
358		break;
359	case mma9551_y:
360		reg = MMA9551_TILT_XZ_ANG_REG;
361		break;
362	case mma9551_z:
363		reg = MMA9551_TILT_XY_ANG_REG;
364		break;
365	}
366
367	/*
368	 * Read the angle even though we don't use it, otherwise we
369	 * won't get any further interrupts.
370	 */
371	ret = mma9551_read_status_byte(data->client, MMA9551_APPID_TILT,
372				       reg, &val);
373	if (ret < 0) {
374		dev_err(&data->client->dev,
375			"error %d reading tilt register in IRQ\n", ret);
376		goto out;
377	}
378
379	iio_push_event(indio_dev,
380		       IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1),
381					  IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING),
382		       iio_get_time_ns(indio_dev));
383
384out:
385	mutex_unlock(&data->mutex);
386
387	return IRQ_HANDLED;
388}
389
390static int mma9551_init(struct mma9551_data *data)
391{
392	int ret;
393
394	ret = mma9551_read_version(data->client);
395	if (ret)
396		return ret;
397
398	return mma9551_set_device_state(data->client, true);
399}
400
401static int mma9551_gpio_probe(struct iio_dev *indio_dev)
402{
403	struct gpio_desc *gpio;
404	int i, ret;
405	struct mma9551_data *data = iio_priv(indio_dev);
406	struct device *dev = &data->client->dev;
407
408	for (i = 0; i < MMA9551_GPIO_COUNT; i++) {
409		gpio = devm_gpiod_get_index(dev, NULL, i, GPIOD_IN);
410		if (IS_ERR(gpio)) {
411			dev_err(dev, "acpi gpio get index failed\n");
412			return PTR_ERR(gpio);
413		}
414
415		ret = gpiod_to_irq(gpio);
416		if (ret < 0)
417			return ret;
418
419		data->irqs[i] = ret;
420		ret = devm_request_threaded_irq(dev, data->irqs[i],
421				NULL, mma9551_event_handler,
422				IRQF_TRIGGER_RISING | IRQF_ONESHOT,
423				"mma9551_event", indio_dev);
424		if (ret < 0) {
425			dev_err(dev, "request irq %d failed\n", data->irqs[i]);
426			return ret;
427		}
428
429		dev_dbg(dev, "gpio resource, no:%d irq:%d\n",
430			desc_to_gpio(gpio), data->irqs[i]);
431	}
432
433	return 0;
434}
435
436static int mma9551_probe(struct i2c_client *client)
437{
438	const struct i2c_device_id *id = i2c_client_get_device_id(client);
439	struct mma9551_data *data;
440	struct iio_dev *indio_dev;
441	const char *name = NULL;
442	int ret;
443
444	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
445	if (!indio_dev)
446		return -ENOMEM;
447
448	data = iio_priv(indio_dev);
449	i2c_set_clientdata(client, indio_dev);
450	data->client = client;
451
452	if (id)
453		name = id->name;
454	else
455		name = iio_get_acpi_device_name(&client->dev);
456
457	ret = mma9551_init(data);
458	if (ret < 0)
459		return ret;
460
461	mutex_init(&data->mutex);
462
463	indio_dev->channels = mma9551_channels;
464	indio_dev->num_channels = ARRAY_SIZE(mma9551_channels);
465	indio_dev->name = name;
466	indio_dev->modes = INDIO_DIRECT_MODE;
467	indio_dev->info = &mma9551_info;
468
469	ret = mma9551_gpio_probe(indio_dev);
470	if (ret < 0)
471		goto out_poweroff;
472
473	ret = pm_runtime_set_active(&client->dev);
474	if (ret < 0)
475		goto out_poweroff;
476
477	pm_runtime_enable(&client->dev);
478	pm_runtime_set_autosuspend_delay(&client->dev,
479					 MMA9551_AUTO_SUSPEND_DELAY_MS);
480	pm_runtime_use_autosuspend(&client->dev);
481
482	ret = iio_device_register(indio_dev);
483	if (ret < 0) {
484		dev_err(&client->dev, "unable to register iio device\n");
485		goto err_pm_cleanup;
486	}
487
488	return 0;
489
490err_pm_cleanup:
491	pm_runtime_dont_use_autosuspend(&client->dev);
492	pm_runtime_disable(&client->dev);
493out_poweroff:
494	mma9551_set_device_state(client, false);
495
496	return ret;
497}
498
499static void mma9551_remove(struct i2c_client *client)
500{
501	struct iio_dev *indio_dev = i2c_get_clientdata(client);
502	struct mma9551_data *data = iio_priv(indio_dev);
503
504	iio_device_unregister(indio_dev);
505
506	pm_runtime_disable(&client->dev);
507	pm_runtime_set_suspended(&client->dev);
508
509	mutex_lock(&data->mutex);
510	mma9551_set_device_state(data->client, false);
511	mutex_unlock(&data->mutex);
512}
513
514static int mma9551_runtime_suspend(struct device *dev)
515{
516	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
517	struct mma9551_data *data = iio_priv(indio_dev);
518	int ret;
519
520	mutex_lock(&data->mutex);
521	ret = mma9551_set_device_state(data->client, false);
522	mutex_unlock(&data->mutex);
523	if (ret < 0) {
524		dev_err(&data->client->dev, "powering off device failed\n");
525		return -EAGAIN;
526	}
527
528	return 0;
529}
530
531static int mma9551_runtime_resume(struct device *dev)
532{
533	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
534	struct mma9551_data *data = iio_priv(indio_dev);
535	int ret;
536
537	ret = mma9551_set_device_state(data->client, true);
538	if (ret < 0)
539		return ret;
540
541	mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE);
542
543	return 0;
544}
545
546static int mma9551_suspend(struct device *dev)
547{
548	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
549	struct mma9551_data *data = iio_priv(indio_dev);
550	int ret;
551
552	mutex_lock(&data->mutex);
553	ret = mma9551_set_device_state(data->client, false);
554	mutex_unlock(&data->mutex);
555
556	return ret;
557}
558
559static int mma9551_resume(struct device *dev)
560{
561	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
562	struct mma9551_data *data = iio_priv(indio_dev);
563	int ret;
564
565	mutex_lock(&data->mutex);
566	ret = mma9551_set_device_state(data->client, true);
567	mutex_unlock(&data->mutex);
568
569	return ret;
570}
571
572static const struct dev_pm_ops mma9551_pm_ops = {
573	SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume)
574	RUNTIME_PM_OPS(mma9551_runtime_suspend, mma9551_runtime_resume, NULL)
575};
576
577static const struct acpi_device_id mma9551_acpi_match[] = {
578	{"MMA9551", 0},
579	{ }
580};
581
582MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match);
583
584static const struct i2c_device_id mma9551_id[] = {
585	{ "mma9551" },
586	{ }
587};
588
589MODULE_DEVICE_TABLE(i2c, mma9551_id);
590
591static struct i2c_driver mma9551_driver = {
592	.driver = {
593		   .name = "mma9551",
594		   .acpi_match_table = mma9551_acpi_match,
595		   .pm = pm_ptr(&mma9551_pm_ops),
596	},
597	.probe = mma9551_probe,
598	.remove = mma9551_remove,
599	.id_table = mma9551_id,
600};
601
602module_i2c_driver(mma9551_driver);
603
604MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
605MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
606MODULE_LICENSE("GPL v2");
607MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver");
608MODULE_IMPORT_NS("IIO_MMA9551");
~/ Read-only file preview.