From patchwork Mon Sep 25 10:07:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harinath Nampally X-Patchwork-Id: 9969565 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 66826602D8 for ; Mon, 25 Sep 2017 10:08:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 55D192624A for ; Mon, 25 Sep 2017 10:08:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 40ED228066; Mon, 25 Sep 2017 10:08:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C439B28A7C for ; Mon, 25 Sep 2017 10:08:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934145AbdIYKH6 (ORCPT ); Mon, 25 Sep 2017 06:07:58 -0400 Received: from mail-oi0-f66.google.com ([209.85.218.66]:36780 "EHLO mail-oi0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933975AbdIYKH4 (ORCPT ); Mon, 25 Sep 2017 06:07:56 -0400 Received: by mail-oi0-f66.google.com with SMTP id a74so3438568oib.3; Mon, 25 Sep 2017 03:07:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=T43ruHJbAUn86uRIKQkd12AhG1TgA8a14o2HQqbOzvE=; b=H+uGGgAXyqkYFyjgivop0iUt6EZmEN4xrsKE4gUk6azlPP8cI0ol4Ft7oAIM3Q6FfV 4h3ltohvUD8EdbOuNZpTqaMthqWwnkt/GB9echfwmv8H0wz9qZd0zDe6Z1JsXsCgWKHZ h36HSiFcWqRljx8zBtbGDVgrDCZm0rqaqgl3z6xY3S4uY0PawqDhBuZVtgRlCb8OKG6e d7etiCwjpLI1kgiuyNOdnw3JnpGJx7EtT4WTEG6mxgYC/DTyrb9s/emLzgLxLHRuFmxu U7drgjDOzOQnlK/Iij8+dCSHcZldx8KdQEQACay5VlZ3X/5ojxkpQImkWRm76LlhvFV5 PgYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=T43ruHJbAUn86uRIKQkd12AhG1TgA8a14o2HQqbOzvE=; b=IBPvqmrYfY+xoof2hh9LbXFK9rjBjNT2rdRxNm3dkIcYLPND6YUSHEA60cEPBfji6J sO3ddOLvZbqVltMiPm0bHP2GhtbXX3jEWjt6aqLAhf4Gv/baTZwaxTCE3rDYMzBQ9g1v WMC5eecarPLD2p+irD+ZQCQeVKxiVEJnrn+2dBjkBR3ppMeuPDAHfCIgAiyX3ofxnqfb MaChDmL3E11NeEYKrQDHl6Qn+oW0LjjKDss+neu/o+fTryjxHV/Oz+xB6Lbuld1ELIQQ St8uqw1zSFjh+Oi8EBMc++0eyXpMqQsClZU7QMaIZgyOFaBrsrpR60nN0HflXDlchfGM A/aQ== X-Gm-Message-State: AHPjjUh8gBLDbjWM3+QuqnlqNWTYtcWb1oz+LK7myN1UWQ8F2oQ4k+CO g9PF6ddQf+cU1CbOOyf2NkI= X-Google-Smtp-Source: AOwi7QCMpJUrRhyY/aq3TrXqhnraIDwPy+L11+NVM3F1mWqQTlLnSE2J9aCG7nOmV4d4f8h6U/A/nA== X-Received: by 10.202.102.36 with SMTP id a36mr8468955oic.83.1506334075140; Mon, 25 Sep 2017 03:07:55 -0700 (PDT) Received: from hary-Aspire-X3400G.Belkin ([97.70.80.173]) by smtp.googlemail.com with ESMTPSA id x206sm6998815oig.55.2017.09.25.03.07.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 25 Sep 2017 03:07:54 -0700 (PDT) From: Harinath Nampally To: jic23@kernel.org Cc: knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, gregkh@linuxfoundation.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, amsfield22@gmail.com, martink@posteo.de Subject: [PATCH 4/4] iio: accel: mma8452: Add single pulse/tap event detection feature for fxls8471. Date: Mon, 25 Sep 2017 06:07:45 -0400 Message-Id: <1506334065-2891-5-git-send-email-harinath922@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1506334065-2891-1-git-send-email-harinath922@gmail.com> References: <1506334065-2891-1-git-send-email-harinath922@gmail.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds following changes to support tap feature: - defines pulse event related registers - enables and handles single pulse interrupt for fxls8471 - handles IIO_EV_DIR_EITHER in read/write callbacks because event direction for pulse is either rising or falling. - configures read/write event value for pulse latency register using IIO_EV_INFO_HYSTERESIS. - add multiple events like pulse and tranient event spec as elements of event_spec array named 'mma8452_accel_events' Except mma8653 chip all other chips like mma845x and fxls8471 have single tap detection feature. Tested thoroughly using iio_event_monitor application on imx6ul-evk board. Signed-off-by: Harinath Nampally --- drivers/iio/accel/mma8452.c | 156 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 5 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 43c3a6b..36f1b56 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -72,6 +72,19 @@ #define MMA8452_TRANSIENT_THS_MASK GENMASK(6, 0) #define MMA8452_TRANSIENT_COUNT 0x20 #define MMA8452_TRANSIENT_CHAN_SHIFT 1 +#define MMA8452_PULSE_CFG 0x21 +#define MMA8452_PULSE_CFG_CHAN(chan) BIT(chan * 2) +#define MMA8452_PULSE_CFG_ELE BIT(6) +#define MMA8452_PULSE_SRC 0x22 +#define MMA8452_PULSE_SRC_XPULSE BIT(4) +#define MMA8452_PULSE_SRC_YPULSE BIT(5) +#define MMA8452_PULSE_SRC_ZPULSE BIT(6) +#define MMA8452_PULSE_THS 0x23 +#define MMA8452_PULSE_THS_MASK GENMASK(6, 0) +#define MMA8452_PULSE_COUNT 0x26 +#define MMA8452_PULSE_CHAN_SHIFT 2 +#define MMA8452_PULSE_LTCY 0x27 + #define MMA8452_CTRL_REG1 0x2a #define MMA8452_CTRL_ACTIVE BIT(0) #define MMA8452_CTRL_DR_MASK GENMASK(5, 3) @@ -91,6 +104,7 @@ #define MMA8452_INT_DRDY BIT(0) #define MMA8452_INT_FF_MT BIT(2) +#define MMA8452_INT_PULSE BIT(3) #define MMA8452_INT_TRANS BIT(5) #define MMA8451_DEVICE_ID 0x1a @@ -155,6 +169,16 @@ static const struct mma8452_event_regs trans_ev_regs = { .ev_count = MMA8452_TRANSIENT_COUNT, }; +static const struct mma8452_event_regs pulse_ev_regs = { + .ev_cfg = MMA8452_PULSE_CFG, + .ev_cfg_ele = MMA8452_PULSE_CFG_ELE, + .ev_cfg_chan_shift = MMA8452_PULSE_CHAN_SHIFT, + .ev_src = MMA8452_PULSE_SRC, + .ev_ths = MMA8452_PULSE_THS, + .ev_ths_mask = MMA8452_PULSE_THS_MASK, + .ev_count = MMA8452_PULSE_COUNT, +}; + /** * struct mma_chip_info - chip specific data * @chip_id: WHO_AM_I register's value @@ -784,6 +808,14 @@ static int mma8452_get_event_regs(struct mma8452_data *data, case IIO_EV_DIR_FALLING: *ev_reg = &ff_mt_ev_regs; return 0; + case IIO_EV_DIR_EITHER: + if (!(data->chip_info->all_events + & MMA8452_INT_PULSE) || + !(data->chip_info->enabled_events + & MMA8452_INT_PULSE)) + return -EINVAL; + *ev_reg = &pulse_ev_regs; + return 0; default: return -EINVAL; } @@ -848,6 +880,25 @@ static int mma8452_read_event_value(struct iio_dev *indio_dev, return ret; } + case IIO_EV_INFO_HYSTERESIS: + if (!(data->chip_info->all_events & MMA8452_INT_PULSE) || + !(data->chip_info->enabled_events & MMA8452_INT_PULSE)) + return -EINVAL; + + ret = i2c_smbus_read_byte_data(data->client, + MMA8452_PULSE_LTCY); + if (ret < 0) + return ret; + + power_mode = mma8452_get_power_mode(data); + if (power_mode < 0) + return power_mode; + + us = ret * mma8452_time_step_us[power_mode][ + mma8452_get_odr_index(data)]; + *val = us / USEC_PER_SEC; + *val2 = us % USEC_PER_SEC; + return IIO_VAL_INT_PLUS_MICRO; default: @@ -908,6 +959,24 @@ static int mma8452_write_event_value(struct iio_dev *indio_dev, return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg); + case IIO_EV_INFO_HYSTERESIS: + if (!(data->chip_info->all_events & MMA8452_INT_PULSE) || + !(data->chip_info->enabled_events & MMA8452_INT_PULSE)) + return -EINVAL; + + ret = mma8452_get_power_mode(data); + if (ret < 0) + return ret; + + steps = (val * USEC_PER_SEC + val2) / + mma8452_time_step_us[ret][ + mma8452_get_odr_index(data)]; + + if (steps < 0 || steps > 0xff) + return -EINVAL; + + return mma8452_change_config(data, MMA8452_PULSE_LTCY, steps); + default: return -EINVAL; } @@ -937,6 +1006,14 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev, return !!(ret & BIT(chan->scan_index + ev_regs->ev_cfg_chan_shift)); + case IIO_EV_DIR_EITHER: + ret = i2c_smbus_read_byte_data(data->client, + ev_regs->ev_cfg); + if (ret < 0) + return ret; + + return !!(ret & BIT(chan->scan_index * + ev_regs->ev_cfg_chan_shift)); default: return -EINVAL; } @@ -988,6 +1065,25 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, val |= ev_regs->ev_cfg_ele; return mma8452_change_config(data, ev_regs->ev_cfg, val); + + case IIO_EV_DIR_EITHER: + val = i2c_smbus_read_byte_data(data->client, ev_regs->ev_cfg); + if (val < 0) + return val; + + if (state) { + val &= ~BIT(chan->scan_index * + ev_regs->ev_cfg_chan_shift); + val |= BIT(chan->scan_index * + ev_regs->ev_cfg_chan_shift); + } else { + val &= ~BIT(chan->scan_index * + ev_regs->ev_cfg_chan_shift); + } + + val |= ev_regs->ev_cfg_ele; + + return mma8452_change_config(data, ev_regs->ev_cfg, val); default: return -EINVAL; } @@ -1025,6 +1121,38 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev) ts); } +static void mma8452_pulse_interrupt(struct iio_dev *indio_dev) +{ + struct mma8452_data *data = iio_priv(indio_dev); + s64 ts = iio_get_time_ns(indio_dev); + int src; + + src = i2c_smbus_read_byte_data(data->client, MMA8452_PULSE_SRC); + if (src < 0) + return; + + if (src & MMA8452_PULSE_SRC_XPULSE) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_EITHER), + ts); + + if (src & MMA8452_PULSE_SRC_YPULSE) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_EITHER), + ts); + + if (src & MMA8452_PULSE_SRC_ZPULSE) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_EITHER), + ts); +} + static irqreturn_t mma8452_interrupt(int irq, void *p) { struct iio_dev *indio_dev = p; @@ -1063,6 +1191,11 @@ static irqreturn_t mma8452_interrupt(int irq, void *p) ret = IRQ_HANDLED; } + if (src & MMA8452_INT_PULSE) { + mma8452_pulse_interrupt(indio_dev); + ret = IRQ_HANDLED; + } + return ret; } @@ -1130,8 +1263,10 @@ static const struct iio_event_spec mma8652_freefall_event[] = { }, }; -static const struct iio_event_spec mma8452_transient_event[] = { + +static const struct iio_event_spec mma8452_accel_events[] = { { + //trasient event .type = IIO_EV_TYPE_MAG, .dir = IIO_EV_DIR_RISING, .mask_separate = BIT(IIO_EV_INFO_ENABLE), @@ -1139,6 +1274,15 @@ static const struct iio_event_spec mma8452_transient_event[] = { BIT(IIO_EV_INFO_PERIOD) | BIT(IIO_EV_INFO_HIGH_PASS_FILTER_3DB) }, + { + //pulse event + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_HYSTERESIS) + }, }; static const struct iio_event_spec mma8452_motion_event[] = { @@ -1202,8 +1346,8 @@ static struct attribute_group mma8452_event_attribute_group = { .shift = 16 - (bits), \ .endianness = IIO_BE, \ }, \ - .event_spec = mma8452_transient_event, \ - .num_event_specs = ARRAY_SIZE(mma8452_transient_event), \ + .event_spec = mma8452_accel_events, \ + .num_event_specs = ARRAY_SIZE(mma8452_accel_events), \ } #define MMA8652_CHANNEL(axis, idx, bits) { \ @@ -1368,9 +1512,11 @@ static const struct mma_chip_info mma_chip_info_table[] = { */ .all_events = MMA8452_INT_DRDY | MMA8452_INT_TRANS | - MMA8452_INT_FF_MT, + MMA8452_INT_FF_MT | + MMA8452_INT_PULSE, .enabled_events = MMA8452_INT_TRANS | - MMA8452_INT_FF_MT, + MMA8452_INT_FF_MT | + MMA8452_INT_PULSE, }, };