diff options
Diffstat (limited to 'drivers/iio/accel/mma9553.c')
| -rw-r--r-- | drivers/iio/accel/mma9553.c | 148 |
1 files changed, 59 insertions, 89 deletions
diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 365a109aaaef..8bfc61824fb2 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c | |||
| @@ -63,8 +63,8 @@ | |||
| 63 | #define MMA9553_MASK_STATUS_STEPCHG BIT(13) | 63 | #define MMA9553_MASK_STATUS_STEPCHG BIT(13) |
| 64 | #define MMA9553_MASK_STATUS_ACTCHG BIT(12) | 64 | #define MMA9553_MASK_STATUS_ACTCHG BIT(12) |
| 65 | #define MMA9553_MASK_STATUS_SUSP BIT(11) | 65 | #define MMA9553_MASK_STATUS_SUSP BIT(11) |
| 66 | #define MMA9553_MASK_STATUS_ACTIVITY (BIT(10) | BIT(9) | BIT(8)) | 66 | #define MMA9553_MASK_STATUS_ACTIVITY GENMASK(10, 8) |
| 67 | #define MMA9553_MASK_STATUS_VERSION 0x00FF | 67 | #define MMA9553_MASK_STATUS_VERSION GENMASK(7, 0) |
| 68 | 68 | ||
| 69 | #define MMA9553_REG_STEPCNT 0x02 | 69 | #define MMA9553_REG_STEPCNT 0x02 |
| 70 | #define MMA9553_REG_DISTANCE 0x04 | 70 | #define MMA9553_REG_DISTANCE 0x04 |
| @@ -76,14 +76,15 @@ | |||
| 76 | #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 | 76 | #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 |
| 77 | #define MMA9553_DEFAULT_GPIO_POLARITY 0 | 77 | #define MMA9553_DEFAULT_GPIO_POLARITY 0 |
| 78 | 78 | ||
| 79 | /* Bitnum used for gpio configuration = bit number in high status byte */ | 79 | /* Bitnum used for GPIO configuration = bit number in high status byte */ |
| 80 | #define STATUS_TO_BITNUM(bit) (ffs(bit) - 9) | 80 | #define MMA9553_STATUS_TO_BITNUM(bit) (ffs(bit) - 9) |
| 81 | #define MMA9553_MAX_BITNUM MMA9553_STATUS_TO_BITNUM(BIT(16)) | ||
| 81 | 82 | ||
| 82 | #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ | 83 | #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ |
| 83 | 84 | ||
| 84 | /* | 85 | /* |
| 85 | * The internal activity level must be stable for ACTTHD samples before | 86 | * The internal activity level must be stable for ACTTHD samples before |
| 86 | * ACTIVITY is updated.The ACTIVITY variable contains the current activity | 87 | * ACTIVITY is updated. The ACTIVITY variable contains the current activity |
| 87 | * level and is updated every time a step is detected or once a second | 88 | * level and is updated every time a step is detected or once a second |
| 88 | * if there are no steps. | 89 | * if there are no steps. |
| 89 | */ | 90 | */ |
| @@ -351,11 +352,11 @@ static int mma9553_conf_gpio(struct mma9553_data *data) | |||
| 351 | * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. | 352 | * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. |
| 352 | */ | 353 | */ |
| 353 | if (activity_enabled && ev_step_detect->enabled) | 354 | if (activity_enabled && ev_step_detect->enabled) |
| 354 | bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); | 355 | bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); |
| 355 | else if (ev_step_detect->enabled) | 356 | else if (ev_step_detect->enabled) |
| 356 | bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); | 357 | bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); |
| 357 | else if (activity_enabled) | 358 | else if (activity_enabled) |
| 358 | bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); | 359 | bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); |
| 359 | else /* Reset */ | 360 | else /* Reset */ |
| 360 | appid = MMA9551_APPID_NONE; | 361 | appid = MMA9551_APPID_NONE; |
| 361 | 362 | ||
| @@ -363,9 +364,12 @@ static int mma9553_conf_gpio(struct mma9553_data *data) | |||
| 363 | return 0; | 364 | return 0; |
| 364 | 365 | ||
| 365 | /* Save initial values for activity and stepcnt */ | 366 | /* Save initial values for activity and stepcnt */ |
| 366 | if (activity_enabled || ev_step_detect->enabled) | 367 | if (activity_enabled || ev_step_detect->enabled) { |
| 367 | mma9553_read_activity_stepcnt(data, &data->activity, | 368 | ret = mma9553_read_activity_stepcnt(data, &data->activity, |
| 368 | &data->stepcnt); | 369 | &data->stepcnt); |
| 370 | if (ret < 0) | ||
| 371 | return ret; | ||
| 372 | } | ||
| 369 | 373 | ||
| 370 | ret = mma9551_gpio_config(data->client, | 374 | ret = mma9551_gpio_config(data->client, |
| 371 | MMA9553_DEFAULT_GPIO_PIN, | 375 | MMA9553_DEFAULT_GPIO_PIN, |
| @@ -396,13 +400,13 @@ static int mma9553_init(struct mma9553_data *data) | |||
| 396 | sizeof(data->conf), (u16 *) &data->conf); | 400 | sizeof(data->conf), (u16 *) &data->conf); |
| 397 | if (ret < 0) { | 401 | if (ret < 0) { |
| 398 | dev_err(&data->client->dev, | 402 | dev_err(&data->client->dev, |
| 399 | "device is not MMA9553L: failed to read cfg regs\n"); | 403 | "failed to read configuration registers\n"); |
| 400 | return ret; | 404 | return ret; |
| 401 | } | 405 | } |
| 402 | 406 | ||
| 403 | 407 | ||
| 404 | /* Reset gpio */ | 408 | /* Reset GPIO */ |
| 405 | data->gpio_bitnum = -1; | 409 | data->gpio_bitnum = MMA9553_MAX_BITNUM; |
| 406 | ret = mma9553_conf_gpio(data); | 410 | ret = mma9553_conf_gpio(data); |
| 407 | if (ret < 0) | 411 | if (ret < 0) |
| 408 | return ret; | 412 | return ret; |
| @@ -436,6 +440,32 @@ static int mma9553_init(struct mma9553_data *data) | |||
| 436 | return mma9551_set_device_state(data->client, true); | 440 | return mma9551_set_device_state(data->client, true); |
| 437 | } | 441 | } |
| 438 | 442 | ||
| 443 | static int mma9553_read_status_word(struct mma9553_data *data, u16 reg, | ||
| 444 | u16 *tmp) | ||
| 445 | { | ||
| 446 | bool powered_on; | ||
| 447 | int ret; | ||
| 448 | |||
| 449 | /* | ||
| 450 | * The HW only counts steps and other dependent | ||
| 451 | * parameters (speed, distance, calories, activity) | ||
| 452 | * if power is on (from enabling an event or the | ||
| 453 | * step counter). | ||
| 454 | */ | ||
| 455 | powered_on = mma9553_is_any_event_enabled(data, false, 0) || | ||
| 456 | data->stepcnt_enabled; | ||
| 457 | if (!powered_on) { | ||
| 458 | dev_err(&data->client->dev, "No channels enabled\n"); | ||
| 459 | return -EINVAL; | ||
| 460 | } | ||
| 461 | |||
| 462 | mutex_lock(&data->mutex); | ||
| 463 | ret = mma9551_read_status_word(data->client, MMA9551_APPID_PEDOMETER, | ||
| 464 | reg, tmp); | ||
| 465 | mutex_unlock(&data->mutex); | ||
| 466 | return ret; | ||
| 467 | } | ||
| 468 | |||
| 439 | static int mma9553_read_raw(struct iio_dev *indio_dev, | 469 | static int mma9553_read_raw(struct iio_dev *indio_dev, |
| 440 | struct iio_chan_spec const *chan, | 470 | struct iio_chan_spec const *chan, |
| 441 | int *val, int *val2, long mask) | 471 | int *val, int *val2, long mask) |
| @@ -444,69 +474,30 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, | |||
| 444 | int ret; | 474 | int ret; |
| 445 | u16 tmp; | 475 | u16 tmp; |
| 446 | u8 activity; | 476 | u8 activity; |
| 447 | bool powered_on; | ||
| 448 | 477 | ||
| 449 | switch (mask) { | 478 | switch (mask) { |
| 450 | case IIO_CHAN_INFO_PROCESSED: | 479 | case IIO_CHAN_INFO_PROCESSED: |
| 451 | switch (chan->type) { | 480 | switch (chan->type) { |
| 452 | case IIO_STEPS: | 481 | case IIO_STEPS: |
| 453 | /* | 482 | ret = mma9553_read_status_word(data, |
| 454 | * The HW only counts steps and other dependent | ||
| 455 | * parameters (speed, distance, calories, activity) | ||
| 456 | * if power is on (from enabling an event or the | ||
| 457 | * step counter */ | ||
| 458 | powered_on = | ||
| 459 | mma9553_is_any_event_enabled(data, false, 0) || | ||
| 460 | data->stepcnt_enabled; | ||
| 461 | if (!powered_on) { | ||
| 462 | dev_err(&data->client->dev, | ||
| 463 | "No channels enabled\n"); | ||
| 464 | return -EINVAL; | ||
| 465 | } | ||
| 466 | mutex_lock(&data->mutex); | ||
| 467 | ret = mma9551_read_status_word(data->client, | ||
| 468 | MMA9551_APPID_PEDOMETER, | ||
| 469 | MMA9553_REG_STEPCNT, | 483 | MMA9553_REG_STEPCNT, |
| 470 | &tmp); | 484 | &tmp); |
| 471 | mutex_unlock(&data->mutex); | ||
| 472 | if (ret < 0) | 485 | if (ret < 0) |
| 473 | return ret; | 486 | return ret; |
| 474 | *val = tmp; | 487 | *val = tmp; |
| 475 | return IIO_VAL_INT; | 488 | return IIO_VAL_INT; |
| 476 | case IIO_DISTANCE: | 489 | case IIO_DISTANCE: |
| 477 | powered_on = | 490 | ret = mma9553_read_status_word(data, |
| 478 | mma9553_is_any_event_enabled(data, false, 0) || | ||
| 479 | data->stepcnt_enabled; | ||
| 480 | if (!powered_on) { | ||
| 481 | dev_err(&data->client->dev, | ||
| 482 | "No channels enabled\n"); | ||
| 483 | return -EINVAL; | ||
| 484 | } | ||
| 485 | mutex_lock(&data->mutex); | ||
| 486 | ret = mma9551_read_status_word(data->client, | ||
| 487 | MMA9551_APPID_PEDOMETER, | ||
| 488 | MMA9553_REG_DISTANCE, | 491 | MMA9553_REG_DISTANCE, |
| 489 | &tmp); | 492 | &tmp); |
| 490 | mutex_unlock(&data->mutex); | ||
| 491 | if (ret < 0) | 493 | if (ret < 0) |
| 492 | return ret; | 494 | return ret; |
| 493 | *val = tmp; | 495 | *val = tmp; |
| 494 | return IIO_VAL_INT; | 496 | return IIO_VAL_INT; |
| 495 | case IIO_ACTIVITY: | 497 | case IIO_ACTIVITY: |
| 496 | powered_on = | 498 | ret = mma9553_read_status_word(data, |
| 497 | mma9553_is_any_event_enabled(data, false, 0) || | ||
| 498 | data->stepcnt_enabled; | ||
| 499 | if (!powered_on) { | ||
| 500 | dev_err(&data->client->dev, | ||
| 501 | "No channels enabled\n"); | ||
| 502 | return -EINVAL; | ||
| 503 | } | ||
| 504 | mutex_lock(&data->mutex); | ||
| 505 | ret = mma9551_read_status_word(data->client, | ||
| 506 | MMA9551_APPID_PEDOMETER, | ||
| 507 | MMA9553_REG_STATUS, | 499 | MMA9553_REG_STATUS, |
| 508 | &tmp); | 500 | &tmp); |
| 509 | mutex_unlock(&data->mutex); | ||
| 510 | if (ret < 0) | 501 | if (ret < 0) |
| 511 | return ret; | 502 | return ret; |
| 512 | 503 | ||
| @@ -531,38 +522,17 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, | |||
| 531 | case IIO_VELOCITY: /* m/h */ | 522 | case IIO_VELOCITY: /* m/h */ |
| 532 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) | 523 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) |
| 533 | return -EINVAL; | 524 | return -EINVAL; |
| 534 | powered_on = | 525 | ret = mma9553_read_status_word(data, |
| 535 | mma9553_is_any_event_enabled(data, false, 0) || | 526 | MMA9553_REG_SPEED, |
| 536 | data->stepcnt_enabled; | 527 | &tmp); |
| 537 | if (!powered_on) { | ||
| 538 | dev_err(&data->client->dev, | ||
| 539 | "No channels enabled\n"); | ||
| 540 | return -EINVAL; | ||
| 541 | } | ||
| 542 | mutex_lock(&data->mutex); | ||
| 543 | ret = mma9551_read_status_word(data->client, | ||
| 544 | MMA9551_APPID_PEDOMETER, | ||
| 545 | MMA9553_REG_SPEED, &tmp); | ||
| 546 | mutex_unlock(&data->mutex); | ||
| 547 | if (ret < 0) | 528 | if (ret < 0) |
| 548 | return ret; | 529 | return ret; |
| 549 | *val = tmp; | 530 | *val = tmp; |
| 550 | return IIO_VAL_INT; | 531 | return IIO_VAL_INT; |
| 551 | case IIO_ENERGY: /* Cal or kcal */ | 532 | case IIO_ENERGY: /* Cal or kcal */ |
| 552 | powered_on = | 533 | ret = mma9553_read_status_word(data, |
| 553 | mma9553_is_any_event_enabled(data, false, 0) || | ||
| 554 | data->stepcnt_enabled; | ||
| 555 | if (!powered_on) { | ||
| 556 | dev_err(&data->client->dev, | ||
| 557 | "No channels enabled\n"); | ||
| 558 | return -EINVAL; | ||
| 559 | } | ||
| 560 | mutex_lock(&data->mutex); | ||
| 561 | ret = mma9551_read_status_word(data->client, | ||
| 562 | MMA9551_APPID_PEDOMETER, | ||
| 563 | MMA9553_REG_CALORIES, | 534 | MMA9553_REG_CALORIES, |
| 564 | &tmp); | 535 | &tmp); |
| 565 | mutex_unlock(&data->mutex); | ||
| 566 | if (ret < 0) | 536 | if (ret < 0) |
| 567 | return ret; | 537 | return ret; |
| 568 | *val = tmp; | 538 | *val = tmp; |
| @@ -789,7 +759,7 @@ static int mma9553_write_event_config(struct iio_dev *indio_dev, | |||
| 789 | 759 | ||
| 790 | mutex_unlock(&data->mutex); | 760 | mutex_unlock(&data->mutex); |
| 791 | 761 | ||
| 792 | return ret; | 762 | return 0; |
| 793 | 763 | ||
| 794 | err_conf_gpio: | 764 | err_conf_gpio: |
| 795 | if (state) { | 765 | if (state) { |
| @@ -897,7 +867,7 @@ static int mma9553_get_calibgender_mode(struct iio_dev *indio_dev, | |||
| 897 | gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); | 867 | gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); |
| 898 | /* | 868 | /* |
| 899 | * HW expects 0 for female and 1 for male, | 869 | * HW expects 0 for female and 1 for male, |
| 900 | * while iio index is 0 for male and 1 for female | 870 | * while iio index is 0 for male and 1 for female. |
| 901 | */ | 871 | */ |
| 902 | return !gender; | 872 | return !gender; |
| 903 | } | 873 | } |
| @@ -944,11 +914,11 @@ static const struct iio_event_spec mma9553_activity_events[] = { | |||
| 944 | }, | 914 | }, |
| 945 | }; | 915 | }; |
| 946 | 916 | ||
| 947 | static const char * const calibgender_modes[] = { "male", "female" }; | 917 | static const char * const mma9553_calibgender_modes[] = { "male", "female" }; |
| 948 | 918 | ||
| 949 | static const struct iio_enum mma9553_calibgender_enum = { | 919 | static const struct iio_enum mma9553_calibgender_enum = { |
| 950 | .items = calibgender_modes, | 920 | .items = mma9553_calibgender_modes, |
| 951 | .num_items = ARRAY_SIZE(calibgender_modes), | 921 | .num_items = ARRAY_SIZE(mma9553_calibgender_modes), |
| 952 | .get = mma9553_get_calibgender_mode, | 922 | .get = mma9553_get_calibgender_mode, |
| 953 | .set = mma9553_set_calibgender_mode, | 923 | .set = mma9553_set_calibgender_mode, |
| 954 | }; | 924 | }; |
| @@ -1110,16 +1080,16 @@ static int mma9553_gpio_probe(struct i2c_client *client) | |||
| 1110 | 1080 | ||
| 1111 | dev = &client->dev; | 1081 | dev = &client->dev; |
| 1112 | 1082 | ||
| 1113 | /* data ready gpio interrupt pin */ | 1083 | /* data ready GPIO interrupt pin */ |
| 1114 | gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN); | 1084 | gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN); |
| 1115 | if (IS_ERR(gpio)) { | 1085 | if (IS_ERR(gpio)) { |
| 1116 | dev_err(dev, "acpi gpio get index failed\n"); | 1086 | dev_err(dev, "ACPI GPIO get index failed\n"); |
| 1117 | return PTR_ERR(gpio); | 1087 | return PTR_ERR(gpio); |
| 1118 | } | 1088 | } |
| 1119 | 1089 | ||
| 1120 | ret = gpiod_to_irq(gpio); | 1090 | ret = gpiod_to_irq(gpio); |
| 1121 | 1091 | ||
| 1122 | dev_dbg(dev, "gpio resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | 1092 | dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); |
| 1123 | 1093 | ||
| 1124 | return ret; | 1094 | return ret; |
| 1125 | } | 1095 | } |
