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