brintos

brintos / linux-shallow public Read only

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