From patchwork Mon Oct 21 05:53:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201401 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9FD0B1575 for ; Mon, 21 Oct 2019 05:55:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6B81F21721 for ; Mon, 21 Oct 2019 05:55:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Jfgl+xH0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726981AbfJUFyP (ORCPT ); Mon, 21 Oct 2019 01:54:15 -0400 Received: from mail-pf1-f194.google.com ([209.85.210.194]:41224 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726394AbfJUFyP (ORCPT ); Mon, 21 Oct 2019 01:54:15 -0400 Received: by mail-pf1-f194.google.com with SMTP id q7so7692414pfh.8 for ; Sun, 20 Oct 2019 22:54:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AdBSi2rqFh7Vdpb3I3tVfeX5I0nWB5o7fC6PgNP0NjU=; b=Jfgl+xH0G/cVghEax9U0ejV4Qz+iIqyt7gM1hlBK0LFNFDRPnlVHyI4q3tT3DZ3qOL R9/5C2fJvS/BVkjKIgmmJEwKwteYO8/vzFminOt8z4RwgWXIxamA3ui+XRvzhewznDop M3MqA6XcKdlkewEmo6UhyRbtTr3WkBOWokoto= 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:mime-version:content-transfer-encoding; bh=AdBSi2rqFh7Vdpb3I3tVfeX5I0nWB5o7fC6PgNP0NjU=; b=lyJIInfIiCd6kQ1NqNktkkugPyWs1kweyPqq5lhtxJGd6fpqBrkVzQf7zTvCQEuPK4 L/cVBa6zyFc47gz9aDeLsB7CakLO1ImwoLMCIyt58JbIRxeOGOj+DA0dLfUF5HbcqBUM ue006Ql1U/clTEKiHPl0Vf9ec9uhkmDEYPz/tqD9Nzd6t/EY0EsSFWNFN/Y2QEjwpczx NKWKP/c0vCil7LngPM8+Nl4TGyRuVp5L32DsqXFTW1LG8fcGQqICDmnA/dx1c8Vu4Gti 9RqXAxtVDUGUp814z2mr9mJI7O82FbbfhWZMMlvpEEQmNvjJiVpAxqKYytdDhXEm2KCX fW2g== X-Gm-Message-State: APjAAAUKx0Uq4aFpZdFdJk0LlKBienbZu66YLWySyz5muoLLLMNIJ3w9 CFN9QmaHX4+PeiyGJBOaChdmrg== X-Google-Smtp-Source: APXvYqwUpQlnenFnhvRw/qIE5AaExdM9R6F2kRHa5O0ipwLqN8BtCpDqTHM0fETGit7+IYggXgyJjg== X-Received: by 2002:a17:90a:bf8d:: with SMTP id d13mr27307999pjs.89.1571637254353; Sun, 20 Oct 2019 22:54:14 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id s141sm15976909pfs.13.2019.10.20.22.54.13 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:13 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 01/18] platform: chrome: Put docs with the code Date: Sun, 20 Oct 2019 22:53:46 -0700 Message-Id: <20191021055403.67849-2-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org To avoid doc rot, put function documentations with code, not header. Use kernel-doc style comments for exported functions. Signed-off-by: Gwendal Grignou Acked-by: Jonathan Cameron --- New in v2. drivers/platform/chrome/cros_ec.c | 33 +++++++ drivers/platform/chrome/cros_ec_proto.c | 70 +++++++++++++ include/linux/platform_data/cros_ec_proto.h | 103 -------------------- 3 files changed, 103 insertions(+), 103 deletions(-) diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index fd77e6fa74c2c..9b2d07422e175 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -104,6 +104,15 @@ static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) return ret; } +/** + * cros_ec_register() - Register a new ChromeOS EC, using the provided info. + * @ec_dev: Device to register. + * + * Before calling this, allocate a pointer to a new device and then fill + * in all the fields up to the --private-- marker. + * + * Return: 0 on success or negative error code. + */ int cros_ec_register(struct cros_ec_device *ec_dev) { struct device *dev = ec_dev->dev; @@ -198,6 +207,14 @@ int cros_ec_register(struct cros_ec_device *ec_dev) } EXPORT_SYMBOL(cros_ec_register); +/** + * cros_ec_unregister() - Remove a ChromeOS EC. + * @ec_dev: Device to unregister. + * + * Call this to deregister a ChromeOS EC, then clean up any private data. + * + * Return: 0 on success or negative error code. + */ int cros_ec_unregister(struct cros_ec_device *ec_dev) { if (ec_dev->pd) @@ -209,6 +226,14 @@ int cros_ec_unregister(struct cros_ec_device *ec_dev) EXPORT_SYMBOL(cros_ec_unregister); #ifdef CONFIG_PM_SLEEP +/** + * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device. + * @ec_dev: Device to suspend. + * + * This can be called by drivers to handle a suspend event. + * + * Return: 0 on success or negative error code. + */ int cros_ec_suspend(struct cros_ec_device *ec_dev) { struct device *dev = ec_dev->dev; @@ -243,6 +268,14 @@ static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev) 1, ec_dev); } +/** + * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device. + * @ec_dev: Device to resume. + * + * This can be called by drivers to handle a resume event. + * + * Return: 0 on success or negative error code. + */ int cros_ec_resume(struct cros_ec_device *ec_dev) { int ret; diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index f659f96bda128..7db58771ec77c 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -117,6 +117,17 @@ static int send_command(struct cros_ec_device *ec_dev, return ret; } +/** + * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer. + * @ec_dev: Device to register. + * @msg: Message to write. + * + * This is intended to be used by all ChromeOS EC drivers, but at present + * only SPI uses it. Once LPC uses the same protocol it can start using it. + * I2C could use it now, with a refactor of the existing code. + * + * Return: 0 on success or negative error code. + */ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) { @@ -141,6 +152,16 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, } EXPORT_SYMBOL(cros_ec_prepare_tx); +/** + * cros_ec_check_result() - Check ec_msg->result. + * @ec_dev: EC device. + * @msg: Message to check. + * + * This is used by ChromeOS EC drivers to check the ec_msg->result for + * errors and to warn about them. + * + * Return: 0 on success or negative error code. + */ int cros_ec_check_result(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) { @@ -326,6 +347,13 @@ static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev, return ret; } +/** + * cros_ec_query_all() - Query the protocol version supported by the + * ChromeOS EC. + * @ec_dev: Device to register. + * + * Return: 0 on success or negative error code. + */ int cros_ec_query_all(struct cros_ec_device *ec_dev) { struct device *dev = ec_dev->dev; @@ -453,6 +481,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) } EXPORT_SYMBOL(cros_ec_query_all); +/** + * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC. + * @ec_dev: EC device. + * @msg: Message to write. + * + * Call this to send a command to the ChromeOS EC. This should be used + * instead of calling the EC's cmd_xfer() callback directly. + * + * Return: 0 on success or negative error code. + */ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) { @@ -500,6 +538,18 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, } EXPORT_SYMBOL(cros_ec_cmd_xfer); +/** + * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC. + * @ec_dev: EC device. + * @msg: Message to write. + * + * This function is identical to cros_ec_cmd_xfer, except it returns success + * status only if both the command was transmitted successfully and the EC + * replied with success status. It's not necessary to check msg->result when + * using this function. + * + * Return: The number of bytes transferred on success or negative error code. + */ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) { @@ -584,6 +634,16 @@ static int get_keyboard_state_event(struct cros_ec_device *ec_dev) return ec_dev->event_size; } +/** + * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC. + * @ec_dev: Device to fetch event from. + * @wake_event: Pointer to a bool set to true upon return if the event might be + * treated as a wake event. Ignored if null. + * + * Return: negative error code on errors; 0 for no data; or else number of + * bytes received (i.e., an event was retrieved successfully). Event types are + * written out to @ec_dev->event_data.event_type on success. + */ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event) { u8 event_type; @@ -628,6 +688,16 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event) } EXPORT_SYMBOL(cros_ec_get_next_event); +/** + * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC. + * @ec_dev: Device to fetch event from. + * + * When MKBP is supported, when the EC raises an interrupt, we collect the + * events raised and call the functions in the ec notifier. This function + * is a helper to know which events are raised. + * + * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*. + */ u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev) { u32 host_event; diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index eab7036cda090..0d4e4aaed37af 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -187,133 +187,30 @@ struct cros_ec_platform { u16 cmd_offset; }; -/** - * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device. - * @ec_dev: Device to suspend. - * - * This can be called by drivers to handle a suspend event. - * - * Return: 0 on success or negative error code. - */ int cros_ec_suspend(struct cros_ec_device *ec_dev); -/** - * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device. - * @ec_dev: Device to resume. - * - * This can be called by drivers to handle a resume event. - * - * Return: 0 on success or negative error code. - */ int cros_ec_resume(struct cros_ec_device *ec_dev); -/** - * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer. - * @ec_dev: Device to register. - * @msg: Message to write. - * - * This is intended to be used by all ChromeOS EC drivers, but at present - * only SPI uses it. Once LPC uses the same protocol it can start using it. - * I2C could use it now, with a refactor of the existing code. - * - * Return: 0 on success or negative error code. - */ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, struct cros_ec_command *msg); -/** - * cros_ec_check_result() - Check ec_msg->result. - * @ec_dev: EC device. - * @msg: Message to check. - * - * This is used by ChromeOS EC drivers to check the ec_msg->result for - * errors and to warn about them. - * - * Return: 0 on success or negative error code. - */ int cros_ec_check_result(struct cros_ec_device *ec_dev, struct cros_ec_command *msg); -/** - * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC. - * @ec_dev: EC device. - * @msg: Message to write. - * - * Call this to send a command to the ChromeOS EC. This should be used - * instead of calling the EC's cmd_xfer() callback directly. - * - * Return: 0 on success or negative error code. - */ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *msg); -/** - * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC. - * @ec_dev: EC device. - * @msg: Message to write. - * - * This function is identical to cros_ec_cmd_xfer, except it returns success - * status only if both the command was transmitted successfully and the EC - * replied with success status. It's not necessary to check msg->result when - * using this function. - * - * Return: The number of bytes transferred on success or negative error code. - */ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, struct cros_ec_command *msg); -/** - * cros_ec_register() - Register a new ChromeOS EC, using the provided info. - * @ec_dev: Device to register. - * - * Before calling this, allocate a pointer to a new device and then fill - * in all the fields up to the --private-- marker. - * - * Return: 0 on success or negative error code. - */ int cros_ec_register(struct cros_ec_device *ec_dev); -/** - * cros_ec_unregister() - Remove a ChromeOS EC. - * @ec_dev: Device to unregister. - * - * Call this to deregister a ChromeOS EC, then clean up any private data. - * - * Return: 0 on success or negative error code. - */ int cros_ec_unregister(struct cros_ec_device *ec_dev); -/** - * cros_ec_query_all() - Query the protocol version supported by the - * ChromeOS EC. - * @ec_dev: Device to register. - * - * Return: 0 on success or negative error code. - */ int cros_ec_query_all(struct cros_ec_device *ec_dev); -/** - * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC. - * @ec_dev: Device to fetch event from. - * @wake_event: Pointer to a bool set to true upon return if the event might be - * treated as a wake event. Ignored if null. - * - * Return: negative error code on errors; 0 for no data; or else number of - * bytes received (i.e., an event was retrieved successfully). Event types are - * written out to @ec_dev->event_data.event_type on success. - */ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event); -/** - * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC. - * @ec_dev: Device to fetch event from. - * - * When MKBP is supported, when the EC raises an interrupt, we collect the - * events raised and call the functions in the ec notifier. This function - * is a helper to know which events are raised. - * - * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*. - */ u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev); #endif /* __LINUX_CROS_EC_PROTO_H */ From patchwork Mon Oct 21 05:53:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201397 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9DB1E112B for ; Mon, 21 Oct 2019 05:55:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 73B2C21721 for ; Mon, 21 Oct 2019 05:55:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="G2dfquF2" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727140AbfJUFyR (ORCPT ); Mon, 21 Oct 2019 01:54:17 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:40453 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727137AbfJUFyR (ORCPT ); Mon, 21 Oct 2019 01:54:17 -0400 Received: by mail-pg1-f194.google.com with SMTP id 15so1720046pgt.7 for ; Sun, 20 Oct 2019 22:54:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qEyxluXdxVFSj/jMNBXEzLvEIlJMi3CeOB42GTMwyU4=; b=G2dfquF20cYNkandnFadc9YFIR4tSUekEPQkLaVobFtzSLigA0PNXMQVaVG497DGLf n9sjLyv5AMz0+MN4yWAt/CUObonujBNFMQVWueApg41fztWyTFFlOWt17Aw8Qdyu/1BZ xvH3F4OEVZ+lDXEnKDf3C9d2KJkC40zqJu95s= 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:mime-version:content-transfer-encoding; bh=qEyxluXdxVFSj/jMNBXEzLvEIlJMi3CeOB42GTMwyU4=; b=PXhDsJu62ieQmLCMiokoo3UjY9HakQpQQGjdI9KAo2j08tF8GrGMOWPHjip3P6Z7Oh AWfHqsbV7s5jjqa56w2x0XM/lGT7b8Kdoep4UZErSqmj7AQ6q8ULJVonDS66BY3lb3cP gGfHXpt8K6QkILUWA0wvVIJe7dpFnudsVnsL0/Cx68L8LdON1UMfQOCtDVge6ZE6w6Qe BKVLYesH7hmxEdaVku9mbFta0py404UaXVIvcGcXUcXnAD6/nHEdBMjY/hE/chKKAkzR wOU1R6VmZFoEde+Lv5i0B+W9qQfbP7G9NXDuvEpp1Qa2o/2qj8Skht4KpD4IV9nQFV9g fHxQ== X-Gm-Message-State: APjAAAUxFK3qdVI173SUzl1Wsg4ijfTG0O1tHK+9VIQ3/7P7jp1bqd5z huiK5HirN3xS63pogWPrnmTcow== X-Google-Smtp-Source: APXvYqx0e8jmp/9286IFC1Pjkblx1JXMirxqxNM6ptnLEnZg0gCpzzJdvzKYquNEiS0zPwZ1w1yrgw== X-Received: by 2002:a17:90a:24e8:: with SMTP id i95mr27533129pje.12.1571637255942; Sun, 20 Oct 2019 22:54:15 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id q132sm14834284pfq.16.2019.10.20.22.54.14 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:15 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 02/18] mfd: cros_ec: Add sensor_count and make check_features public Date: Sun, 20 Oct 2019 22:53:47 -0700 Message-Id: <20191021055403.67849-3-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add a new function to return the number of MEMS sensors available in a ChromeOS Embedded Controller. It uses MOTIONSENSE_CMD_DUMP if available or a specific memory map ACPI registers to find out. Also, make check_features public as it can be useful for other drivers to know what the Embedded Controller supports. Signed-off-by: Gwendal Grignou --- Changes in v2: Fix spelling in commit message. Cleanup the case where DUMP command is not supported. Move code from mfd to platform/chrome/ drivers/mfd/cros_ec_dev.c | 32 ------ drivers/platform/chrome/cros_ec_proto.c | 116 ++++++++++++++++++++ include/linux/platform_data/cros_ec_proto.h | 5 + 3 files changed, 121 insertions(+), 32 deletions(-) diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 6e6dfd6c18711..a35104e35cb4e 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -112,38 +112,6 @@ static const struct mfd_cell cros_ec_vbc_cells[] = { { .name = "cros-ec-vbc", } }; -static int cros_ec_check_features(struct cros_ec_dev *ec, int feature) -{ - struct cros_ec_command *msg; - int ret; - - if (ec->features[0] == -1U && ec->features[1] == -1U) { - /* features bitmap not read yet */ - msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL); - if (!msg) - return -ENOMEM; - - msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset; - msg->insize = sizeof(ec->features); - - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); - if (ret < 0) { - dev_warn(ec->dev, "cannot get EC features: %d/%d\n", - ret, msg->result); - memset(ec->features, 0, sizeof(ec->features)); - } else { - memcpy(ec->features, msg->data, sizeof(ec->features)); - } - - dev_dbg(ec->dev, "EC features %08x %08x\n", - ec->features[0], ec->features[1]); - - kfree(msg); - } - - return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature); -} - static void cros_ec_class_release(struct device *dev) { kfree(to_cros_ec_dev(dev)); diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 7db58771ec77c..2357c717399ad 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -717,3 +717,119 @@ u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev) return host_event; } EXPORT_SYMBOL(cros_ec_get_host_event); + +/** + * cros_ec_check_features - Test for the presence of EC features + * + * Call this function to test whether the ChromeOS EC supports a feature. + * + * @ec_dev: EC device: does not have to be connected directly to the AP, + * can be daisy chained through another device. + * @feature: One of ec_feature_code bit. + * @return: 1 if supported, 0 if not + */ +int cros_ec_check_features(struct cros_ec_dev *ec, int feature) +{ + struct cros_ec_command *msg; + int ret; + + if (ec->features[0] == -1U && ec->features[1] == -1U) { + /* features bitmap not read yet */ + msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset; + msg->insize = sizeof(ec->features); + + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0) { + dev_warn(ec->dev, "cannot get EC features: %d/%d\n", + ret, msg->result); + memset(ec->features, 0, sizeof(ec->features)); + } else { + memcpy(ec->features, msg->data, sizeof(ec->features)); + } + + dev_dbg(ec->dev, "EC features %08x %08x\n", + ec->features[0], ec->features[1]); + + kfree(msg); + } + + return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature); +} +EXPORT_SYMBOL_GPL(cros_ec_check_features); + +/** + * Return the number of MEMS sensors supported. + * + * @ec_dev: EC device: does not have to be connected directly to the AP, + * can be daisy chained through another device. + * Return < 0 in case of error. + */ +int cros_ec_get_sensor_count(struct cros_ec_dev *ec) +{ + /* + * Issue a command to get the number of sensor reported. + * If not supported, check for legacy mode. + */ + int ret, sensor_count; + struct ec_params_motion_sense *params; + struct ec_response_motion_sense *resp; + struct cros_ec_command *msg; + struct cros_ec_device *ec_dev = ec->ec_dev; + u8 status; + + msg = kzalloc(sizeof(struct cros_ec_command) + + max(sizeof(*params), sizeof(*resp)), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + msg->version = 1; + msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; + msg->outsize = sizeof(*params); + msg->insize = sizeof(*resp); + + params = (struct ec_params_motion_sense *)msg->data; + params->cmd = MOTIONSENSE_CMD_DUMP; + + ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + if (ret < 0) { + sensor_count = ret; + } else if (msg->result != EC_RES_SUCCESS) { + sensor_count = -EPROTO; + } else { + resp = (struct ec_response_motion_sense *)msg->data; + sensor_count = resp->dump.sensor_count; + } + kfree(msg); + + /* + * Check legacy mode: Let's find out if sensors are accessible + * via LPC interface. + */ + if (sensor_count == -EPROTO && + ec->cmd_offset == 0 && + ec_dev->cmd_readmem) { + ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, + 1, &status); + if ((ret >= 0) && + (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) { + /* + * We have 2 sensors, one in the lid, one in the base. + */ + sensor_count = 2; + } else { + /* + * EC uses LPC interface and no sensors are presented. + */ + sensor_count = 0; + } + } else if (sensor_count == -EPROTO) { + /* EC responded, but does not understand DUMP command. */ + sensor_count = 0; + } + return sensor_count; +} +EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count); diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index 0d4e4aaed37af..f3de0662135d5 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -12,6 +12,7 @@ #include #include +#include #include #define CROS_EC_DEV_NAME "cros_ec" @@ -213,4 +214,8 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event); u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev); +int cros_ec_check_features(struct cros_ec_dev *ec, int feature); + +int cros_ec_get_sensor_count(struct cros_ec_dev *ec); + #endif /* __LINUX_CROS_EC_PROTO_H */ From patchwork Mon Oct 21 05:53:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201395 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 428F6112B for ; Mon, 21 Oct 2019 05:55:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1725C214D9 for ; Mon, 21 Oct 2019 05:55:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="NP4rkaxA" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726039AbfJUFyU (ORCPT ); Mon, 21 Oct 2019 01:54:20 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:32934 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727186AbfJUFyU (ORCPT ); Mon, 21 Oct 2019 01:54:20 -0400 Received: by mail-pg1-f194.google.com with SMTP id i76so7087446pgc.0 for ; Sun, 20 Oct 2019 22:54:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jNdNwdC6V0v+WrsvZXqWxZ9sXp+abWqhpIVYfeQWSe0=; b=NP4rkaxAvC1IAb03T92BZj8zUNKrZyJTSEMh4UzM4tLMZ/x31NQy+RtZ1RcmRksloE RhVS9sn9/KqCYi+DUAlIn6g2aArjqzjDy2FsLvjQejQcvW3P+B27evkwoRliyiHtUwIP G+ye2gUtWFq7UnSlTAxup4jdt2t7b42fap0oo= 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:mime-version:content-transfer-encoding; bh=jNdNwdC6V0v+WrsvZXqWxZ9sXp+abWqhpIVYfeQWSe0=; b=neg5XvP8X7ypUaA/6flmSrhpS/wOutSLsID/kB81vi5UU2q+kX8tDA2lfR+l8DtNwH LH6L+z7iKhfl+D+gOXr9qSq2UJnjvYX3poteWZjxgOm4VIVozH3rt1lZa/KoDjmrZ17D gd6oWZWvdb1uAOtFIimx6U26GOhcm+DUhefIGBxvB7NiLC0po2mz9U3EVQtoL3pADR7J 7OEfjIDBZB6YY7rKb4fMzqxEpRaGmFynu+VvTGbGHFjKdqYdM33sBAZPCTRN3Vg/ZFkZ 1O+YxYq8qkdEOlu1/yvVxy/Z8F7zw1FdFsiFszDc99shaDhrnMV6vqPnfrHN8VXv8hXw gA+Q== X-Gm-Message-State: APjAAAVe9WCXwJf1lTpOrsYMD4J2VBjdv5zgzW1Pn/J2vTibr4Jro6rs uWtXpx2csN+yfOWG/Cm1sTAqXQ== X-Google-Smtp-Source: APXvYqxqSdIOE4Pui4lpFvX4laOsEVG6+nA+GAsjFHLmYaKI/e0yoEy7EWb43Xh5hoHeKEpUAZQiRw== X-Received: by 2002:a63:3816:: with SMTP id f22mr18248293pga.430.1571637257315; Sun, 20 Oct 2019 22:54:17 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id m9sm13441620pjf.11.2019.10.20.22.54.16 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:16 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 03/18] platform: cros_ec: Add cros_ec_sensor_hub driver Date: Sun, 20 Oct 2019 22:53:48 -0700 Message-Id: <20191021055403.67849-4-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Similar to HID sensor stack, the new driver sits between cros_ec_dev and the iio device drivers: EC based iio device topology would be: iio:device1 -> ...0/0000:00:1f.0/PNP0C09:00/GOOG0004:00/cros-ec-dev.6.auto/ cros-ec-sensorhub.7.auto/ cros-ec-accel.15.auto/ iio:device1 It will be expanded to control EC sensor FIFO. Signed-off-by: Gwendal Grignou --- Changes in v2: - Remove unerelated changes. - Fix spelling. - Use !x instead of x == NULL - Use platform_ API directly to register IIO sensors from cros_ec_sensorhub. drivers/iio/common/cros_ec_sensors/Kconfig | 2 +- drivers/platform/chrome/Kconfig | 12 ++ drivers/platform/chrome/Makefile | 1 + drivers/platform/chrome/cros_ec_sensorhub.c | 202 ++++++++++++++++++ .../linux/platform_data/cros_ec_sensorhub.h | 21 ++ 5 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 drivers/platform/chrome/cros_ec_sensorhub.c create mode 100644 include/linux/platform_data/cros_ec_sensorhub.h diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig index cdbb29cfb9076..fefad95727907 100644 --- a/drivers/iio/common/cros_ec_sensors/Kconfig +++ b/drivers/iio/common/cros_ec_sensors/Kconfig @@ -4,7 +4,7 @@ # config IIO_CROS_EC_SENSORS_CORE tristate "ChromeOS EC Sensors Core" - depends on SYSFS && CROS_EC + depends on SYSFS && CROS_EC_SENSORHUB select IIO_BUFFER select IIO_TRIGGERED_BUFFER help diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index ee5f08ea57b6c..56a25317a6bee 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -190,6 +190,18 @@ config CROS_EC_DEBUGFS To compile this driver as a module, choose M here: the module will be called cros_ec_debugfs. +config CROS_EC_SENSORHUB + tristate "ChromeOS EC MEMS Sensor Hub" + depends on CROS_EC && IIO + help + Allow loading IIO sensors. This driver is loaded by MFD and will in + turn query the EC and register the sensors. + It also spreads the sensor data coming from the EC to the IIO sensor + object. + + To compile this driver as a module, choose M here: the + module will be called cros_ec_sensorhub. + config CROS_EC_SYSFS tristate "ChromeOS EC control and information through sysfs" depends on MFD_CROS_EC_DEV && SYSFS diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index 477ec3d1d1c98..a164c40dc0996 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.o obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o +obj-$(CONFIG_CROS_EC_SENSORHUB) += cros_ec_sensorhub.o obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c b/drivers/platform/chrome/cros_ec_sensorhub.c new file mode 100644 index 0000000000000..5fea4c28c5c95 --- /dev/null +++ b/drivers/platform/chrome/cros_ec_sensorhub.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SensorHub: driver that discover sensors behind + * a ChromeOS Embedded controller. + * + * Copyright 2019 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "cros-ec-sensorhub" + + +static struct device_type cros_ec_sensorhub_dev_type = { + .name = "cros_ec_iio_sensor", +}; + +static int cros_ec_sensorhub_allocate_single_sensor( + struct device *parent, + char *sensor_name, + int sensor_num) +{ + struct platform_device *pdev; + struct cros_ec_sensor_platform sensor_platforms = { + .sensor_num = sensor_num, + }; + int ret; + + pdev = platform_device_alloc(sensor_name, PLATFORM_DEVID_AUTO); + if (!pdev) + return -ENOMEM; + + pdev->dev.parent = parent; + pdev->dev.type = &cros_ec_sensorhub_dev_type; + + ret = platform_device_add_data(pdev, &sensor_platforms, + sizeof(sensor_platforms)); + if (ret) + goto fail_device; + + ret = platform_device_add(pdev); + if (ret) + goto fail_device; + + return 0; + +fail_device: + platform_device_put(pdev); + return ret; +} + +static int cros_ec_sensorhub_register(struct device *dev, + struct cros_ec_dev *ec) +{ + int ret, i, id, sensor_num; + int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 }; + struct ec_params_motion_sense *params; + struct ec_response_motion_sense *resp; + struct cros_ec_command *msg; + char *name; + + sensor_num = cros_ec_get_sensor_count(ec); + if (sensor_num < 0) { + dev_err(dev, + "Unable to retrieve sensor information (err:%d)\n", + sensor_num); + return sensor_num; + } + + if (sensor_num == 0) { + dev_err(dev, "Zero sensors reported.\n"); + return -EINVAL; + } + + /* Prepare a message to send INFO command to each sensor. */ + msg = kzalloc(sizeof(struct cros_ec_command) + + max(sizeof(*params), sizeof(*resp)), GFP_KERNEL); + if (!msg) { + ret = -ENOMEM; + goto error; + } + + msg->version = 1; + msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; + msg->outsize = sizeof(*params); + msg->insize = sizeof(*resp); + params = (struct ec_params_motion_sense *)msg->data; + resp = (struct ec_response_motion_sense *)msg->data; + + id = 0; + for (i = 0; i < sensor_num; i++) { + params->cmd = MOTIONSENSE_CMD_INFO; + params->info.sensor_num = i; + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0) { + dev_warn(dev, "no info for EC sensor %d : %d/%d\n", + i, ret, msg->result); + continue; + } + switch (resp->info.type) { + case MOTIONSENSE_TYPE_ACCEL: + name = "cros-ec-accel"; + break; + case MOTIONSENSE_TYPE_BARO: + name = "cros-ec-baro"; + break; + case MOTIONSENSE_TYPE_GYRO: + name = "cros-ec-gyro"; + break; + case MOTIONSENSE_TYPE_MAG: + name = "cros-ec-mag"; + break; + case MOTIONSENSE_TYPE_PROX: + name = "cros-ec-prox"; + break; + case MOTIONSENSE_TYPE_LIGHT: + name = "cros-ec-light"; + break; + case MOTIONSENSE_TYPE_ACTIVITY: + name = "cros-ec-activity"; + break; + default: + dev_warn(dev, "unknown type %d\n", resp->info.type); + continue; + } + ret = cros_ec_sensorhub_allocate_single_sensor(dev, name, i); + if (ret) + goto error; + + sensor_type[resp->info.type]++; + } + + if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) + ec->has_kb_wake_angle = true; + + if (cros_ec_check_features(ec, + EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) { + ret = cros_ec_sensorhub_allocate_single_sensor( + dev, "cros-ec-lid-angle", 0); + } + +error: + kfree(msg); + return ret; +} + +static int cros_ec_sensorhub_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); + int ret; + struct cros_ec_sensorhub *data = + kzalloc(sizeof(struct cros_ec_sensorhub), GFP_KERNEL); + + if (!data) + return -ENOMEM; + + data->ec = ec; + dev_set_drvdata(dev, data); + + /* Check whether this EC is a sensor hub. */ + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) { + ret = cros_ec_sensorhub_register(dev, ec); + } else { + ret = cros_ec_sensorhub_allocate_single_sensor( + dev, "cros-ec-accel-legacy", 0); + ret |= cros_ec_sensorhub_allocate_single_sensor( + dev, "cros-ec-accel-legacy", 1); + } + if (ret) + dev_err(dev, "failed to add EC sensors: error %d\n", ret); + return ret; +} + +static struct platform_driver cros_ec_sensorhub_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = cros_ec_sensorhub_probe, +}; + +module_platform_driver(cros_ec_sensorhub_driver); + +MODULE_ALIAS("platform:" DRV_NAME); +MODULE_AUTHOR("Gwendal Grignou "); +MODULE_DESCRIPTION("ChromeOS EC MEMS Sensor Hub Driver"); +MODULE_LICENSE("GPL"); + diff --git a/include/linux/platform_data/cros_ec_sensorhub.h b/include/linux/platform_data/cros_ec_sensorhub.h new file mode 100644 index 0000000000000..7737685591ad3 --- /dev/null +++ b/include/linux/platform_data/cros_ec_sensorhub.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * cros_ec_sensorhub- Chrome OS EC MEMS Sensor Hub driver. + * + * Copyright (C) 2019 Google, Inc + */ + +#ifndef __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H +#define __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H + +#include + +/* + * struct cros_ec_sensorhub - Sensor Hub device data. + */ +struct cros_ec_sensorhub { + /* Embedded Controller where the hub is located. */ + struct cros_ec_dev *ec; +}; + +#endif /* __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H */ From patchwork Mon Oct 21 05:53:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201393 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B565E1575 for ; Mon, 21 Oct 2019 05:55:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8A27A214D9 for ; Mon, 21 Oct 2019 05:55:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Mj/0SUa4" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727218AbfJUFyU (ORCPT ); Mon, 21 Oct 2019 01:54:20 -0400 Received: from mail-pg1-f196.google.com ([209.85.215.196]:46752 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727167AbfJUFyT (ORCPT ); Mon, 21 Oct 2019 01:54:19 -0400 Received: by mail-pg1-f196.google.com with SMTP id e15so7049287pgu.13 for ; Sun, 20 Oct 2019 22:54:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RDkpSFqUW1OYsAziIdJbhhH6w6jepHUtz2gKWVCmpwI=; b=Mj/0SUa4r2uu04XKQWe4GS+qmaLRdMJGrnzgoCRtx/nEPe2byeDPFA3PMPVZVEo+Rf Clz1xEhKOCHkmNQnfYPZ7mqCSeZtIVpMxOKLKW5H3AZzEFC1tNlyhLILx1rE10nrsXkF vkXPASH2lbdexM4VkwPFq38TNrRYgo+qS/nBs= 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:mime-version:content-transfer-encoding; bh=RDkpSFqUW1OYsAziIdJbhhH6w6jepHUtz2gKWVCmpwI=; b=lTRjeRCEP1YTbJTMKD5S/yHz+o2VL7CzaFotx7Ew8VVtEsiFO4ZxcdM4Rim0u+uQxy eK6Gy6fakXywfh3aYhaMObQbABDCo38wUQJBe7ErQInL3JSmNxig3OBdgk2wJk4cBlTP P+PkOB5zigm/U3Fm7rd26cZAzyP43jG7g8gskZLHy7LT0HdOhH8dpUqCm77H6LcoSxA3 IjRctB+mrFFI1rVPSJ2vV9dVKzM4J91JTy+cFpTQk0ll0otkrdbhcSX34mQp1Gm4KV8h 2MrGosb74hG5CiH5KqO+boV3J/dPFySszfjlIb1B6qQavsfAfdeFaWnsxehwz2TxnEvl o63Q== X-Gm-Message-State: APjAAAVH0sFXbY9Ru1ntot9K9huYs/OPTuwvslb67SCG/iWdu9zwWS7+ jdYR4RVNIbFYcjV3Gc0ngBqu8A== X-Google-Smtp-Source: APXvYqw77uViqlDpl6RSIh0qbEBZpLXKR7C9Z4/iuP55kEP1UIPGxeqrI8H6B9p+hogoRajB+LVfwQ== X-Received: by 2002:aa7:956a:: with SMTP id x10mr20527539pfq.14.1571637258646; Sun, 20 Oct 2019 22:54:18 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id r21sm21458165pfc.27.2019.10.20.22.54.17 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:18 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 04/18] platform/mfd:iio: cros_ec: Register sensor through sensorhub Date: Sun, 20 Oct 2019 22:53:49 -0700 Message-Id: <20191021055403.67849-5-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org - Remove duplicate code in mfd, since mfd just register cros_ec_sensorhub if at least one sensor is present - Change iio cros_ec driver to get the pointer to the cros_ec_dev through cros_ec_sensorhub. Signed-off-by: Gwendal Grignou Acked-by: Jonathan Cameron Acked-by: Enric Balletbo i Serra --- Changes in v2: - Remove unerelated changes. - Remove ec presence test in iio driver, done in cros_ec_sensorhub. drivers/iio/accel/cros_ec_accel_legacy.c | 6 - .../common/cros_ec_sensors/cros_ec_sensors.c | 6 - .../cros_ec_sensors/cros_ec_sensors_core.c | 4 +- drivers/iio/light/cros_ec_light_prox.c | 6 - drivers/mfd/cros_ec_dev.c | 203 ++---------------- include/linux/platform_data/cros_ec_proto.h | 8 - .../linux/platform_data/cros_ec_sensorhub.h | 8 + 7 files changed, 23 insertions(+), 218 deletions(-) diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index fcc3f999e4827..65f85faf6f31d 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -163,16 +163,10 @@ static const struct iio_chan_spec cros_ec_accel_legacy_channels[] = { static int cros_ec_accel_legacy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); struct iio_dev *indio_dev; struct cros_ec_sensors_core_state *state; int ret; - if (!ec || !ec->ec_dev) { - dev_warn(&pdev->dev, "No EC device found.\n"); - return -EINVAL; - } - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); if (!indio_dev) return -ENOMEM; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index a6987726eeb8a..7dce044734678 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -222,17 +222,11 @@ static const struct iio_info ec_sensors_info = { static int cros_ec_sensors_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); struct iio_dev *indio_dev; struct cros_ec_sensors_state *state; struct iio_chan_spec *channel; int ret, i; - if (!ec_dev || !ec_dev->ec_dev) { - dev_warn(&pdev->dev, "No CROS EC device found.\n"); - return -EINVAL; - } - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); if (!indio_dev) return -ENOMEM; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index d2609e6feda4d..81a7f692de2f3 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -18,6 +18,7 @@ #include #include #include +#include #include static char *cros_ec_loc[] = { @@ -88,7 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, { struct device *dev = &pdev->dev; struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); - struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); + struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent); + struct cros_ec_dev *ec = sensor_hub->ec; struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); u32 ver_mask; int ret, i; diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index c5263b563fc19..d85a391e50c59 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -169,17 +169,11 @@ static const struct iio_info cros_ec_light_prox_info = { static int cros_ec_light_prox_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent); struct iio_dev *indio_dev; struct cros_ec_light_prox_state *state; struct iio_chan_spec *channel; int ret; - if (!ec_dev || !ec_dev->ec_dev) { - dev_warn(dev, "No CROS EC device found.\n"); - return -EINVAL; - } - indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); if (!indio_dev) return -ENOMEM; diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index a35104e35cb4e..c4b977a5dd966 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -78,6 +78,10 @@ static const struct mfd_cell cros_ec_rtc_cells[] = { { .name = "cros-ec-rtc", }, }; +static const struct mfd_cell cros_ec_sensorhub_cells[] = { + { .name = "cros-ec-sensorhub", }, +}; + static const struct mfd_cell cros_usbpd_charger_cells[] = { { .name = "cros-usbpd-charger", }, { .name = "cros-usbpd-logger", }, @@ -117,192 +121,6 @@ static void cros_ec_class_release(struct device *dev) kfree(to_cros_ec_dev(dev)); } -static void cros_ec_sensors_register(struct cros_ec_dev *ec) -{ - /* - * Issue a command to get the number of sensor reported. - * Build an array of sensors driver and register them all. - */ - int ret, i, id, sensor_num; - struct mfd_cell *sensor_cells; - struct cros_ec_sensor_platform *sensor_platforms; - int sensor_type[MOTIONSENSE_TYPE_MAX]; - struct ec_params_motion_sense *params; - struct ec_response_motion_sense *resp; - struct cros_ec_command *msg; - - msg = kzalloc(sizeof(struct cros_ec_command) + - max(sizeof(*params), sizeof(*resp)), GFP_KERNEL); - if (msg == NULL) - return; - - msg->version = 2; - msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; - msg->outsize = sizeof(*params); - msg->insize = sizeof(*resp); - - params = (struct ec_params_motion_sense *)msg->data; - params->cmd = MOTIONSENSE_CMD_DUMP; - - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); - if (ret < 0) { - dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n", - ret, msg->result); - goto error; - } - - resp = (struct ec_response_motion_sense *)msg->data; - sensor_num = resp->dump.sensor_count; - /* - * Allocate 2 extra sensors if lid angle sensor and/or FIFO are needed. - */ - sensor_cells = kcalloc(sensor_num + 2, sizeof(struct mfd_cell), - GFP_KERNEL); - if (sensor_cells == NULL) - goto error; - - sensor_platforms = kcalloc(sensor_num, - sizeof(struct cros_ec_sensor_platform), - GFP_KERNEL); - if (sensor_platforms == NULL) - goto error_platforms; - - memset(sensor_type, 0, sizeof(sensor_type)); - id = 0; - for (i = 0; i < sensor_num; i++) { - params->cmd = MOTIONSENSE_CMD_INFO; - params->info.sensor_num = i; - ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); - if (ret < 0) { - dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n", - i, ret, msg->result); - continue; - } - switch (resp->info.type) { - case MOTIONSENSE_TYPE_ACCEL: - sensor_cells[id].name = "cros-ec-accel"; - break; - case MOTIONSENSE_TYPE_BARO: - sensor_cells[id].name = "cros-ec-baro"; - break; - case MOTIONSENSE_TYPE_GYRO: - sensor_cells[id].name = "cros-ec-gyro"; - break; - case MOTIONSENSE_TYPE_MAG: - sensor_cells[id].name = "cros-ec-mag"; - break; - case MOTIONSENSE_TYPE_PROX: - sensor_cells[id].name = "cros-ec-prox"; - break; - case MOTIONSENSE_TYPE_LIGHT: - sensor_cells[id].name = "cros-ec-light"; - break; - case MOTIONSENSE_TYPE_ACTIVITY: - sensor_cells[id].name = "cros-ec-activity"; - break; - default: - dev_warn(ec->dev, "unknown type %d\n", resp->info.type); - continue; - } - sensor_platforms[id].sensor_num = i; - sensor_cells[id].id = sensor_type[resp->info.type]; - sensor_cells[id].platform_data = &sensor_platforms[id]; - sensor_cells[id].pdata_size = - sizeof(struct cros_ec_sensor_platform); - - sensor_type[resp->info.type]++; - id++; - } - - if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) - ec->has_kb_wake_angle = true; - - if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { - sensor_cells[id].name = "cros-ec-ring"; - id++; - } - if (cros_ec_check_features(ec, - EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) { - sensor_cells[id].name = "cros-ec-lid-angle"; - id++; - } - - ret = mfd_add_devices(ec->dev, 0, sensor_cells, id, - NULL, 0, NULL); - if (ret) - dev_err(ec->dev, "failed to add EC sensors\n"); - - kfree(sensor_platforms); -error_platforms: - kfree(sensor_cells); -error: - kfree(msg); -} - -static struct cros_ec_sensor_platform sensor_platforms[] = { - { .sensor_num = 0 }, - { .sensor_num = 1 } -}; - -static const struct mfd_cell cros_ec_accel_legacy_cells[] = { - { - .name = "cros-ec-accel-legacy", - .platform_data = &sensor_platforms[0], - .pdata_size = sizeof(struct cros_ec_sensor_platform), - }, - { - .name = "cros-ec-accel-legacy", - .platform_data = &sensor_platforms[1], - .pdata_size = sizeof(struct cros_ec_sensor_platform), - } -}; - -static void cros_ec_accel_legacy_register(struct cros_ec_dev *ec) -{ - struct cros_ec_device *ec_dev = ec->ec_dev; - u8 status; - int ret; - - /* - * ECs that need legacy support are the main EC, directly connected to - * the AP. - */ - if (ec->cmd_offset != 0) - return; - - /* - * Check if EC supports direct memory reads and if EC has - * accelerometers. - */ - if (ec_dev->cmd_readmem) { - ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, 1, - &status); - if (ret < 0) { - dev_warn(ec->dev, "EC direct read error.\n"); - return; - } - - /* Check if EC has accelerometers. */ - if (!(status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) { - dev_info(ec->dev, "EC does not have accelerometers.\n"); - return; - } - } - - /* - * The device may still support accelerometers: - * it would be an older ARM based device that do not suppor the - * EC_CMD_GET_FEATURES command. - * - * Register 2 accelerometers, we will fail in the IIO driver if there - * are no sensors. - */ - ret = mfd_add_hotplug_devices(ec->dev, cros_ec_accel_legacy_cells, - ARRAY_SIZE(cros_ec_accel_legacy_cells)); - if (ret) - dev_err(ec_dev->dev, "failed to add EC sensors\n"); -} - static int ec_device_probe(struct platform_device *pdev) { int retval = -ENOMEM; @@ -358,11 +176,14 @@ static int ec_device_probe(struct platform_device *pdev) goto failed; /* check whether this EC is a sensor hub. */ - if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) - cros_ec_sensors_register(ec); - else - /* Workaroud for older EC firmware */ - cros_ec_accel_legacy_register(ec); + if (cros_ec_get_sensor_count(ec) > 0) { + retval = mfd_add_hotplug_devices(ec->dev, + cros_ec_sensorhub_cells, + ARRAY_SIZE(cros_ec_sensorhub_cells)); + if (retval) + dev_err(ec->dev, "failed to add %s subdevice: %d\n", + cros_ec_sensorhub_cells->name, retval); + } /* * The following subdevices can be detected by sending the diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index f3de0662135d5..691f9e953a96a 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -168,14 +168,6 @@ struct cros_ec_device { struct platform_device *pd; }; -/** - * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information. - * @sensor_num: Id of the sensor, as reported by the EC. - */ -struct cros_ec_sensor_platform { - u8 sensor_num; -}; - /** * struct cros_ec_platform - ChromeOS EC platform information. * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...) diff --git a/include/linux/platform_data/cros_ec_sensorhub.h b/include/linux/platform_data/cros_ec_sensorhub.h index 7737685591ad3..c18fba660bb62 100644 --- a/include/linux/platform_data/cros_ec_sensorhub.h +++ b/include/linux/platform_data/cros_ec_sensorhub.h @@ -10,6 +10,14 @@ #include +/** + * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information. + * @sensor_num: Id of the sensor, as reported by the EC. + */ +struct cros_ec_sensor_platform { + u8 sensor_num; +}; + /* * struct cros_ec_sensorhub - Sensor Hub device data. */ From patchwork Mon Oct 21 05:53:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201365 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 32332112B for ; Mon, 21 Oct 2019 05:54:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0801920700 for ; Mon, 21 Oct 2019 05:54:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="ZpEFp6r/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726128AbfJUFy0 (ORCPT ); Mon, 21 Oct 2019 01:54:26 -0400 Received: from mail-pg1-f196.google.com ([209.85.215.196]:37039 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727259AbfJUFyW (ORCPT ); Mon, 21 Oct 2019 01:54:22 -0400 Received: by mail-pg1-f196.google.com with SMTP id p1so7079466pgi.4 for ; Sun, 20 Oct 2019 22:54:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BJbX4lCaaBJmkHIqy8k6zUpKVDZ3oHKPcTTsAqbAYog=; b=ZpEFp6r/eDkYFsjaUEjYnJV6pRAVCTSlSmxS+xD36gVg4NEYhfIbHJq+9jgALodwT2 1XG/HjNwwoKKBKn2omTQZtimj/AffEraYrAdZtHxfN2izF+RPV5omohMDc1jt5pzO9Ss cjhKbQJaXkY+HUk6hlp0XSObmSkIzPM+MB/pg= 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:mime-version:content-transfer-encoding; bh=BJbX4lCaaBJmkHIqy8k6zUpKVDZ3oHKPcTTsAqbAYog=; b=hGtWNkYlsm7r42vKC8lAVjMVG12rNaA/84FUY9fLH2UnLgsgYD8iGxi0ubASKHfEXi pooRFOwLhpyB3c/r8ISH3wYO8rk6TcPy4K4aVrgpMWgV33q20mNKSbYzUpt6SaJ1BPtn odftMj/tinsXr0LhREJVeEzHG1zjzXQFM2M2F0X509ijP5XmILSyRVPS6d5Gu/k3Bd6a xdqjM77RQFKstGnSVXMV67TZsy+DwjStdeJyRRNc7eaw53XK4Dme8Hms7gQCIll0sa9y dIqoHbknGI+eGMFpEUStpGOz2rZYkaiL7m0dJr+C+MTtTHzZ+EIhuBwYB0yFC/erFUcq YsFw== X-Gm-Message-State: APjAAAVUVqImO7KKtc9oDv4FJnFk+oLJTGydsc9+fu11Yt7nJgvv6PoQ pQSbnXGycyzrNf4H+T1JHoyu2Q== X-Google-Smtp-Source: APXvYqzTCSBJTUEbPHIZbFCI3dta0ng0DlAajvfNk4fFwM0fcWM7vy6qngpEeMSHstdrts1bCrEDpw== X-Received: by 2002:a62:ab03:: with SMTP id p3mr20724603pff.88.1571637260338; Sun, 20 Oct 2019 22:54:20 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id g20sm13789956pfo.73.2019.10.20.22.54.19 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:19 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 05/18] platform: chrome: cros-ec: record event timestamp in the hard irq Date: Sun, 20 Oct 2019 22:53:50 -0700 Message-Id: <20191021055403.67849-6-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org To improve sensor timestamp precision, given EC and AP are in different time domains, the AP needs to try to record the exact moment an event was signalled to the AP by the EC as soon as possible after it happens. First thing in the hard irq is the best place for this. Signed-off-by: Gwendal Grignou --- Changes in v2: Make cros_ec_get_time_ns inline. Using ktime_t instead of s64 when dealing with time. Added code in ishtp to gather timestamp. drivers/platform/chrome/cros_ec.c | 12 +++++++++++- drivers/platform/chrome/cros_ec_ishtp.c | 17 +++++++++++++++-- drivers/platform/chrome/cros_ec_lpc.c | 2 ++ include/linux/platform_data/cros_ec_proto.h | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index 9b2d07422e175..739f3cffe26e3 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -31,6 +31,15 @@ static struct cros_ec_platform pd_p = { .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX), }; +static irqreturn_t ec_irq_handler(int irq, void *data) +{ + struct cros_ec_device *ec_dev = data; + + ec_dev->last_event_time = cros_ec_get_time_ns(); + + return IRQ_WAKE_THREAD; +} + static irqreturn_t ec_irq_thread(int irq, void *data) { struct cros_ec_device *ec_dev = data; @@ -141,7 +150,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev) } if (ec_dev->irq) { - err = devm_request_threaded_irq(dev, ec_dev->irq, NULL, + err = devm_request_threaded_irq( + dev, ec_dev->irq, ec_irq_handler, ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "chromeos-ec", ec_dev); if (err) { diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c index 25ca2c894b4de..5c848f22b44b4 100644 --- a/drivers/platform/chrome/cros_ec_ishtp.c +++ b/drivers/platform/chrome/cros_ec_ishtp.c @@ -200,13 +200,14 @@ static int ish_send(struct ishtp_cl_data *client_data, * process_recv() - Received and parse incoming packet * @cros_ish_cl: Client instance to get stats * @rb_in_proc: Host interface message buffer + * @timestamp: Timestamp of when parent callback started * * Parse the incoming packet. If it is a response packet then it will * update per instance flags and wake up the caller waiting to for the * response. If it is an event packet then it will schedule event work. */ static void process_recv(struct ishtp_cl *cros_ish_cl, - struct ishtp_cl_rb *rb_in_proc) + struct ishtp_cl_rb *rb_in_proc, ktime_t timestamp) { size_t data_len = rb_in_proc->buf_idx; struct ishtp_cl_data *client_data = @@ -295,6 +296,11 @@ static void process_recv(struct ishtp_cl *cros_ish_cl, break; case CROS_MKBP_EVENT: + /* + * Set timestamp from beginning of function since we actually + * got an incoming MKBP event + */ + client_data->ec_dev->last_event_time = timestamp; /* The event system doesn't send any data in buffer */ schedule_work(&client_data->work_ec_evt); @@ -322,10 +328,17 @@ static void ish_event_cb(struct ishtp_cl_device *cl_device) { struct ishtp_cl_rb *rb_in_proc; struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device); + ktime_t timestamp; + + /* + * Take timestamp as close to hardware interrupt as possible for sensor + * timestamps. + */ + timestamp = cros_ec_get_time_ns(); while ((rb_in_proc = ishtp_cl_rx_get_rb(cros_ish_cl)) != NULL) { /* Decide what to do with received data */ - process_recv(cros_ish_cl, rb_in_proc); + process_recv(cros_ish_cl, rb_in_proc, timestamp); } } diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 7d10d909435ff..3c77496e164da 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -313,6 +313,8 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) { struct cros_ec_device *ec_dev = data; + ec_dev->last_event_time = cros_ec_get_time_ns(); + if (ec_dev->mkbp_event_supported && cros_ec_get_next_event(ec_dev, NULL) > 0) blocking_notifier_call_chain(&ec_dev->event_notifier, 0, diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index 691f9e953a96a..b183024fef1f6 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -122,6 +122,8 @@ struct cros_ec_command { * @event_data: Raw payload transferred with the MKBP event. * @event_size: Size in bytes of the event data. * @host_event_wake_mask: Mask of host events that cause wake from suspend. + * @last_event_time: exact time from the hard irq when we got notified of + * a new event. * @ec: The platform_device used by the mfd driver to interface with the * main EC. * @pd: The platform_device used by the mfd driver to interface with the @@ -162,6 +164,7 @@ struct cros_ec_device { int event_size; u32 host_event_wake_mask; u32 last_resume_result; + ktime_t last_event_time; /* The platform devices used by the mfd driver */ struct platform_device *ec; @@ -210,4 +213,17 @@ int cros_ec_check_features(struct cros_ec_dev *ec, int feature); int cros_ec_get_sensor_count(struct cros_ec_dev *ec); +/** + * cros_ec_get_time_ns - Return time in ns. + * + * This is the function used to record the time for last_event_time in struct + * cros_ec_device during the hard irq. + * + * Return: ktime_t format since boot. + */ +static inline ktime_t cros_ec_get_time_ns(void) +{ + return ktime_get_boottime_ns(); +} + #endif /* __LINUX_CROS_EC_PROTO_H */ From patchwork Mon Oct 21 05:53:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201363 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ABABE1575 for ; Mon, 21 Oct 2019 05:54:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 800EB21479 for ; Mon, 21 Oct 2019 05:54:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="QEsYal5I" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727280AbfJUFyX (ORCPT ); Mon, 21 Oct 2019 01:54:23 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:43490 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727260AbfJUFyW (ORCPT ); Mon, 21 Oct 2019 01:54:22 -0400 Received: by mail-pf1-f193.google.com with SMTP id a2so7691506pfo.10 for ; Sun, 20 Oct 2019 22:54:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8emxxlyv0hfOTgOOWBUsQUpOlmvH2jBaXtEtprCbnfQ=; b=QEsYal5IjLMhnSvwqYnWTC1cGImeuZg5zYsuCBeORCFFYfeGHipQQiEWg6jKzClb+c MZTu3m9mT3MSVcuS3NJY3HI/kgL7aEOc1iuYar+t5pWRxe/9Pu75j56hWm6IhNHaFqAV E+g8aQdvYFktGh2uoqA/QpTmX9bA8cd0mR3Zg= 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:mime-version:content-transfer-encoding; bh=8emxxlyv0hfOTgOOWBUsQUpOlmvH2jBaXtEtprCbnfQ=; b=RMfKczYs/4NMJSxH9+KMiQiYvtwo3fj7KQqIqIybJ1TtEiaE9nfSbeYzWeg7UqNBj4 9ASfP7dkFfW6FpK5T2wM9zgm2FI2qunU91yaNOPoyD9vrDR5qRGwihct6BosGnS6Eu2w zfBnHO1QA8sNNWvwI7dbpneF5q8BWK3RIk1gHs8lArKWKFyNOLUvMCZKDC9P50ACWC1U J6s4uFOEh1Za1QZ9hEZhwSnrkwU8b8jlxsFpUPjLNYtJnQEY40HAovlunmUm4t9tDxYD 0qXiGCu7++XtJlkjeLNLvpw2OSl1vkWpDb8nyDznP7Po0AujOJdyPz6c5MmiTIhnjJ+y F/GA== X-Gm-Message-State: APjAAAX7nremdRtOvgc+wl1tYt7kpn/+N1siYALPXix/nnAi7fzFLiU1 Ro0ha6ZGuQYryzs2CgeRQ0BQug== X-Google-Smtp-Source: APXvYqx2iXs9sZJnmULUcwsogTtABgRk9/VAH8NymvwT5xOT+nEept4zrlkYzUNbZBVIoiwwZKFkrA== X-Received: by 2002:a65:5541:: with SMTP id t1mr23450120pgr.39.1571637261616; Sun, 20 Oct 2019 22:54:21 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id l62sm15062699pfl.167.2019.10.20.22.54.20 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:21 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Enrico Granata , Gwendal Grignou Subject: [PATCH v2 06/18] platform: chrome: cros_ec: Do not attempt to register a non-positive IRQ number Date: Sun, 20 Oct 2019 22:53:51 -0700 Message-Id: <20191021055403.67849-7-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Enrico Granata Add a layer of sanity checking to cros_ec_register against attempting to register IRQ values that are not strictly greater than 0. Signed-off-by: Enrico Granata Signed-off-by: Gwendal Grignou --- Changes in v2: Remove dual Enrico's signature. drivers/platform/chrome/cros_ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index 739f3cffe26e3..9b19f50572313 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -149,7 +149,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) return err; } - if (ec_dev->irq) { + if (ec_dev->irq > 0) { err = devm_request_threaded_irq( dev, ec_dev->irq, ec_irq_handler, ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, From patchwork Mon Oct 21 05:53:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201387 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AB2B41575 for ; Mon, 21 Oct 2019 05:55:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 75DAF2089C for ; Mon, 21 Oct 2019 05:55:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="BhNGJUyt" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727276AbfJUFyZ (ORCPT ); Mon, 21 Oct 2019 01:54:25 -0400 Received: from mail-pf1-f195.google.com ([209.85.210.195]:46823 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727237AbfJUFyY (ORCPT ); Mon, 21 Oct 2019 01:54:24 -0400 Received: by mail-pf1-f195.google.com with SMTP id q5so7681249pfg.13 for ; Sun, 20 Oct 2019 22:54:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TKD6AR0vyytH1MCSlAKEE6e1YrzOf72638oCHoKkjAY=; b=BhNGJUytIP6y4sXBok0ArIFkR0A2vZS1BsiU7biBilvSleT+wDP49+aJ1MEB8v+FZN BiT1HRVF6IeDJ+/4r9gpbFnVgXnS2Hz83eEKDw9bA0pPrrNnJVrN7HKaB3Aqq0vPBO3x lMh6ZWCL4E+MQvmvD8gDx5nXpHUg3AHjQ1uec= 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:mime-version:content-transfer-encoding; bh=TKD6AR0vyytH1MCSlAKEE6e1YrzOf72638oCHoKkjAY=; b=BZXd4+9PsdKj91OJc/5iQEL7q5ABVYZSOKEJ5/RRMSKC8dhcuuESNvUrLU1b2yeyni 11PZOd2fTQV9D/DdF+oVcd88rP6gheMZKJ2jr+ILVTWMXXBZAT4wAMbqfOh7aCaU4v2E 1Xk5ycwxkggUT3nfiJBqQQZ7teuLSJWGWBK779Pc5JKytQrhFu21vcMwoE02ohQABFCs Wm3GX6pUQHPoDVY9liNIJmTXJnSwcOLQMa3kazw4rHu1uPfrwoMOAiBKdzTaDjLqNXKK YUoPE8Ec0nqgLGmFhVqomfYXml5q7FLO4ubxe/8/7Ls24C5XSMVg8RmGvTvjppAz/R4S is9w== X-Gm-Message-State: APjAAAXY0xcXH1zPXvTSIzCHyBlJrgF8BKW9sS8sZ91c+QJd2gsDKJEw Aq4QVRBMT6RwrCAGILcvZuZQQ1sTNrI= X-Google-Smtp-Source: APXvYqxicdN5vv0uWXwcmPTr8eP5I8C+8gaZZvd9F0BU+Jbqv4fX1ptbe1hsHbZPKlt5n1veyS+RUg== X-Received: by 2002:a63:ff08:: with SMTP id k8mr23505588pgi.8.1571637263238; Sun, 20 Oct 2019 22:54:23 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id m22sm13726288pgd.45.2019.10.20.22.54.22 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:22 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Enrico Granata , Gwendal Grignou Subject: [PATCH v2 07/18] platform: chrome: cros_ec: handle MKBP more events flag Date: Sun, 20 Oct 2019 22:53:52 -0700 Message-Id: <20191021055403.67849-8-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Enrico Granata The ChromeOS EC has support for signaling to the host that a single IRQ can serve multiple MKBP (Matrix KeyBoard Protocol) events. Doing this serves an optimization purpose, as it minimizes the number of round-trips into the interrupt handling machinery, and it proves beneficial to sensor timestamping as it keeps the desired synchronization of event times between the two processors. This patch adds kernel support for this EC feature, allowing the ec_irq to loop until all events have been served. Signed-off-by: Enrico Granata Signed-off-by: Gwendal Grignou --- Changes in v2: Process flag inside cros_ec_get_next_event, clean flag from event. Introduce public function cros_ec_handle_event(), use it in rpmsg and ishtp transport layer. Remplace dev_info with dev_dbg, call only once. drivers/platform/chrome/cros_ec.c | 35 +++++++-- drivers/platform/chrome/cros_ec_ishtp.c | 8 +- drivers/platform/chrome/cros_ec_lpc.c | 15 +++- drivers/platform/chrome/cros_ec_proto.c | 81 +++++++++++++-------- drivers/platform/chrome/cros_ec_rpmsg.c | 23 ++---- include/linux/platform_data/cros_ec_proto.h | 12 ++- 6 files changed, 110 insertions(+), 64 deletions(-) diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index 9b19f50572313..eb7f60140e2c1 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -40,13 +40,24 @@ static irqreturn_t ec_irq_handler(int irq, void *data) return IRQ_WAKE_THREAD; } -static irqreturn_t ec_irq_thread(int irq, void *data) +/** + * cros_ec_handle_event - process and forward pending events on EC + * + * Call this function in a loop when the kernel is notified that the EC has + * pending events. + * + * Returns true if more events are still pending and this function should be + * called again. + */ +bool cros_ec_handle_event(struct cros_ec_device *ec_dev) { - struct cros_ec_device *ec_dev = data; - bool wake_event = true; + bool wake_event; + bool ec_has_more_events; int ret; - ret = cros_ec_get_next_event(ec_dev, &wake_event); + ret = cros_ec_get_next_event(ec_dev, + &wake_event, + &ec_has_more_events); /* * Signal only if wake host events or any interrupt if @@ -59,6 +70,20 @@ static irqreturn_t ec_irq_thread(int irq, void *data) if (ret > 0) blocking_notifier_call_chain(&ec_dev->event_notifier, 0, ec_dev); + + return ec_has_more_events; +} +EXPORT_SYMBOL(cros_ec_handle_event); + +static irqreturn_t ec_irq_thread(int irq, void *data) +{ + struct cros_ec_device *ec_dev = data; + bool ec_has_more_events; + + do { + ec_has_more_events = cros_ec_handle_event(ec_dev); + } while (ec_has_more_events); + return IRQ_HANDLED; } @@ -273,7 +298,7 @@ EXPORT_SYMBOL(cros_ec_suspend); static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev) { while (ec_dev->mkbp_event_supported && - cros_ec_get_next_event(ec_dev, NULL) > 0) + cros_ec_get_next_event(ec_dev, NULL, NULL) > 0) blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev); } diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c index 5c848f22b44b4..e5996821d08b3 100644 --- a/drivers/platform/chrome/cros_ec_ishtp.c +++ b/drivers/platform/chrome/cros_ec_ishtp.c @@ -136,11 +136,11 @@ static void ish_evt_handler(struct work_struct *work) struct ishtp_cl_data *client_data = container_of(work, struct ishtp_cl_data, work_ec_evt); struct cros_ec_device *ec_dev = client_data->ec_dev; + bool ec_has_more_events; - if (cros_ec_get_next_event(ec_dev, NULL) > 0) { - blocking_notifier_call_chain(&ec_dev->event_notifier, - 0, ec_dev); - } + do { + ec_has_more_events = cros_ec_handle_event(ec_dev); + } while (ec_has_more_events); } /** diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 3c77496e164da..7d2db3d2b094a 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -312,13 +312,20 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset, static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) { struct cros_ec_device *ec_dev = data; + bool ec_has_more_events; + int ret; ec_dev->last_event_time = cros_ec_get_time_ns(); - if (ec_dev->mkbp_event_supported && - cros_ec_get_next_event(ec_dev, NULL) > 0) - blocking_notifier_call_chain(&ec_dev->event_notifier, 0, - ec_dev); + if (ec_dev->mkbp_event_supported) + do { + ret = cros_ec_get_next_event(ec_dev, NULL, + &ec_has_more_events); + if (ret > 0) + blocking_notifier_call_chain( + &ec_dev->event_notifier, 0, + ec_dev); + } while (ec_has_more_events); if (value == ACPI_NOTIFY_DEVICE_WAKE) pm_system_wakeup(); diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 2357c717399ad..17d6f36a576d1 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -456,7 +456,10 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) if (ret < 0 || ver_mask == 0) ec_dev->mkbp_event_supported = 0; else - ec_dev->mkbp_event_supported = 1; + ec_dev->mkbp_event_supported = fls(ver_mask); + + dev_dbg(ec_dev->dev, "MKBP support version %u\n", + ec_dev->mkbp_event_supported - 1); /* Probe if host sleep v1 is supported for S0ix failure detection. */ ret = cros_ec_get_host_command_version_mask(ec_dev, @@ -569,6 +572,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer_status); static int get_next_event_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *msg, + struct ec_response_get_next_event_v1 *event, int version, uint32_t size) { int ret; @@ -581,7 +585,7 @@ static int get_next_event_xfer(struct cros_ec_device *ec_dev, ret = cros_ec_cmd_xfer(ec_dev, msg); if (ret > 0) { ec_dev->event_size = ret - 1; - memcpy(&ec_dev->event_data, msg->data, ret); + ec_dev->event_data = *event; } return ret; @@ -589,30 +593,26 @@ static int get_next_event_xfer(struct cros_ec_device *ec_dev, static int get_next_event(struct cros_ec_device *ec_dev) { - u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)]; - struct cros_ec_command *msg = (struct cros_ec_command *)&buffer; - static int cmd_version = 1; - int ret; + struct { + struct cros_ec_command msg; + struct ec_response_get_next_event_v1 event; + } __packed buf; + struct cros_ec_command *msg = &buf.msg; + struct ec_response_get_next_event_v1 *event = &buf.event; + const int cmd_version = ec_dev->mkbp_event_supported - 1; + memset(msg, 0, sizeof(*msg)); if (ec_dev->suspended) { dev_dbg(ec_dev->dev, "Device suspended.\n"); return -EHOSTDOWN; } - if (cmd_version == 1) { - ret = get_next_event_xfer(ec_dev, msg, cmd_version, - sizeof(struct ec_response_get_next_event_v1)); - if (ret < 0 || msg->result != EC_RES_INVALID_VERSION) - return ret; - - /* Fallback to version 0 for future send attempts */ - cmd_version = 0; - } - - ret = get_next_event_xfer(ec_dev, msg, cmd_version, + if (cmd_version == 0) + return get_next_event_xfer(ec_dev, msg, event, 0, sizeof(struct ec_response_get_next_event)); - return ret; + return get_next_event_xfer(ec_dev, msg, event, cmd_version, + sizeof(struct ec_response_get_next_event_v1)); } static int get_keyboard_state_event(struct cros_ec_device *ec_dev) @@ -639,32 +639,55 @@ static int get_keyboard_state_event(struct cros_ec_device *ec_dev) * @ec_dev: Device to fetch event from. * @wake_event: Pointer to a bool set to true upon return if the event might be * treated as a wake event. Ignored if null. + * @has_more_events: Pointer to bool set to true if more than one event is + * pending. + * Some EC will set this flag to indicate cros_ec_get_next_event() + * can be called multiple times in a row. + * It is an optimization to prevent issuing a EC command for + * nothing or wait for another interrupt from the EC to process + * the next message. + * Ignored if null. * * Return: negative error code on errors; 0 for no data; or else number of * bytes received (i.e., an event was retrieved successfully). Event types are * written out to @ec_dev->event_data.event_type on success. */ -int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event) +int cros_ec_get_next_event(struct cros_ec_device *ec_dev, + bool *wake_event, + bool *has_more_events) { u8 event_type; u32 host_event; int ret; - if (!ec_dev->mkbp_event_supported) { - ret = get_keyboard_state_event(ec_dev); - if (ret <= 0) - return ret; + /* + * Default value for wake_event. + * Wake up on keyboard event, wake up for spurious interrupt or link + * error to the EC. + */ + if (wake_event) + *wake_event = true; - if (wake_event) - *wake_event = true; + /* + * Default value for has_more_events. + * EC will raise another interrupt if AP does not process all events + * anyway. + */ + if (has_more_events) + *has_more_events = false; - return ret; - } + if (!ec_dev->mkbp_event_supported) + return get_keyboard_state_event(ec_dev); ret = get_next_event(ec_dev); if (ret <= 0) return ret; + if (has_more_events) + *has_more_events = ec_dev->event_data.event_type & + EC_MKBP_HAS_MORE_EVENTS; + ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK; + if (wake_event) { event_type = ec_dev->event_data.event_type; host_event = cros_ec_get_host_event(ec_dev); @@ -679,11 +702,7 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event) else if (host_event && !(host_event & ec_dev->host_event_wake_mask)) *wake_event = false; - /* Consider all other events as wake events. */ - else - *wake_event = true; } - return ret; } EXPORT_SYMBOL(cros_ec_get_next_event); diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c index 0c3738c3244d8..7aa3be42d8e3f 100644 --- a/drivers/platform/chrome/cros_ec_rpmsg.c +++ b/drivers/platform/chrome/cros_ec_rpmsg.c @@ -140,25 +140,14 @@ static void cros_ec_rpmsg_host_event_function(struct work_struct *host_event_work) { struct cros_ec_rpmsg *ec_rpmsg = container_of(host_event_work, - struct cros_ec_rpmsg, - host_event_work); + struct cros_ec_rpmsg, + host_event_work); struct cros_ec_device *ec_dev = dev_get_drvdata(&ec_rpmsg->rpdev->dev); - bool wake_event = true; - int ret; - - ret = cros_ec_get_next_event(ec_dev, &wake_event); - - /* - * Signal only if wake host events or any interrupt if - * cros_ec_get_next_event() returned an error (default value for - * wake_event is true) - */ - if (wake_event && device_may_wakeup(ec_dev->dev)) - pm_wakeup_event(ec_dev->dev, 0); + bool ec_has_more_events; - if (ret > 0) - blocking_notifier_call_chain(&ec_dev->event_notifier, - 0, ec_dev); + do { + ec_has_more_events = cros_ec_handle_event(ec_dev); + } while (ec_has_more_events); } static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data, diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index b183024fef1f6..e238930ae9670 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -116,7 +116,9 @@ struct cros_ec_command { * code. * @pkt_xfer: Send packet to EC and get response. * @lock: One transaction at a time. - * @mkbp_event_supported: True if this EC supports the MKBP event protocol. + * @mkbp_event_supported: 0 if MKBP not supported. Otherwise its value is + * the maximum supported version of the MKBP host event + * command + 1. * @host_sleep_v1: True if this EC supports the sleep v1 command. * @event_notifier: Interrupt event notifier for transport devices. * @event_data: Raw payload transferred with the MKBP event. @@ -156,7 +158,7 @@ struct cros_ec_device { int (*pkt_xfer)(struct cros_ec_device *ec, struct cros_ec_command *msg); struct mutex lock; - bool mkbp_event_supported; + u8 mkbp_event_supported; bool host_sleep_v1; struct blocking_notifier_head event_notifier; @@ -205,7 +207,9 @@ int cros_ec_unregister(struct cros_ec_device *ec_dev); int cros_ec_query_all(struct cros_ec_device *ec_dev); -int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event); +int cros_ec_get_next_event(struct cros_ec_device *ec_dev, + bool *wake_event, + bool *has_more_events); u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev); @@ -213,6 +217,8 @@ int cros_ec_check_features(struct cros_ec_dev *ec, int feature); int cros_ec_get_sensor_count(struct cros_ec_dev *ec); +bool cros_ec_handle_event(struct cros_ec_device *ec_dev); + /** * cros_ec_get_time_ns - Return time in ns. * From patchwork Mon Oct 21 05:53:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201389 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 88ECA112B for ; Mon, 21 Oct 2019 05:55:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 67FB621479 for ; Mon, 21 Oct 2019 05:55:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="dcTyKTJX" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726199AbfJUFzK (ORCPT ); Mon, 21 Oct 2019 01:55:10 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:34557 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725794AbfJUFyZ (ORCPT ); Mon, 21 Oct 2019 01:54:25 -0400 Received: by mail-pf1-f196.google.com with SMTP id b128so7715646pfa.1 for ; Sun, 20 Oct 2019 22:54:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hX0C6B+JnRorkRcAH+QZtlo4gKeiA3mE2oXHCalaLuk=; b=dcTyKTJX2xKLB4Zw2xVpiQuOXNlCEBWCedHV+KVgVKnlKxoXdQNW/gJaKSzFkiCiDR 6CLZrsO+TYjy4Jc2eBIjqX9+s6z+UroT5wYzzC3A/j14pOlaExYTTOIhtW+/PdqSvd9L jyI3g70DvS9e6vPZt2biPYx7Z0aCPrmQVZzWQ= 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:mime-version:content-transfer-encoding; bh=hX0C6B+JnRorkRcAH+QZtlo4gKeiA3mE2oXHCalaLuk=; b=t6noG3DGCmC55YUsxfRSnwVt8YF1nYu+G0GuZu3OcSGwGyaVbCPnwoWQz7T2Sl9Y7Z D5djyawUaCXFPC3XWfTFHcIssmcfuoXoSjW1wsEkvatXgZkg8s3xcPHSUDrInnsGD2w7 WgLh6LZ5Qe9345bdtlfCEvUWyxQFt1gGRv7TLsiOcYcj4oLdKf3ZVMZDBbqgQA8KwDlG 9MISyWxQN68MlcV5IfuWGm6fdKCztb+5E1qwu6qRujOYqF/XxpMraGU/Q4WBY8asYaAU Yd1+vkszkBQHgN7qdGZT99lVynG3Jc/yOzojquFxs1+D1dvFIxnvqJByJe+8ZWn26i2T VJZg== X-Gm-Message-State: APjAAAXYeQmztaF/ZwM6lznTQlG0TnE9IOYpV8Lp+DTuzwBoqkEa78uZ WeS8L/WCHXKKMAMAfFPnCGbr4wLNwpA= X-Google-Smtp-Source: APXvYqydxQF2RicEsD7rpkJfMdv6kyRfYVhicrlOuWuABQ9tge3/6scXgRqNHd4YyZ4I69FKH7nDpQ== X-Received: by 2002:a63:f34f:: with SMTP id t15mr24512541pgj.453.1571637264657; Sun, 20 Oct 2019 22:54:24 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id g35sm12964961pgl.27.2019.10.20.22.54.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:24 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 08/18] Revert "Input: cros_ec_keyb - add back missing mask for event_type" Date: Sun, 20 Oct 2019 22:53:53 -0700 Message-Id: <20191021055403.67849-9-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org This reverts commit 62c3801619e16b68a37ea899b76572145dfe41c9. This patch is not needed anymore since we clear EC_MKBP_HAS_MORE_EVENTS flag before calling the notifiers in patch "9d9518f5b52a (platform: chrome: cros_ec: handle MKBP more events flag)" Signed-off-by: Gwendal Grignou --- New to v2. drivers/input/keyboard/cros_ec_keyb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 8d4d9786cc745..a29e81fdf1861 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -226,8 +226,6 @@ static int cros_ec_keyb_work(struct notifier_block *nb, { struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb, notifier); - uint8_t mkbp_event_type = ckdev->ec->event_data.event_type & - EC_MKBP_EVENT_TYPE_MASK; u32 val; unsigned int ev_type; @@ -239,7 +237,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb, if (queued_during_suspend && !device_may_wakeup(ckdev->dev)) return NOTIFY_OK; - switch (mkbp_event_type) { + switch (ckdev->ec->event_data.event_type & EC_MKBP_EVENT_TYPE_MASK) { case EC_MKBP_EVENT_KEY_MATRIX: pm_wakeup_event(ckdev->dev, 0); @@ -266,7 +264,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb, case EC_MKBP_EVENT_SWITCH: pm_wakeup_event(ckdev->dev, 0); - if (mkbp_event_type == EC_MKBP_EVENT_BUTTON) { + if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) { val = get_unaligned_le32( &ckdev->ec->event_data.data.buttons); ev_type = EV_KEY; From patchwork Mon Oct 21 05:53:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201367 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 004C6112B for ; Mon, 21 Oct 2019 05:54:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D28B321721 for ; Mon, 21 Oct 2019 05:54:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="dy0NE2JV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727294AbfJUFya (ORCPT ); Mon, 21 Oct 2019 01:54:30 -0400 Received: from mail-pg1-f193.google.com ([209.85.215.193]:37047 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727287AbfJUFy2 (ORCPT ); Mon, 21 Oct 2019 01:54:28 -0400 Received: by mail-pg1-f193.google.com with SMTP id p1so7079606pgi.4 for ; Sun, 20 Oct 2019 22:54:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=agTpXvCTTB9wh7DBugiS1SMOpvplNNTL1004RlqbTps=; b=dy0NE2JV2NoCiDdxCroYxnRuBoAKSlSsMWVmpKZ9481xU7i8pVhw4NYGcBY5eSKVmn rY5u70XMTEtwAB98UY8IMLRrrfx/MpkH3r11oJntxhbUT3FO4qALKi8finJbe3s7nKxy 4Q/krUxvl4JGy+F95QjajqGoihNkBgqHFo6Vs= 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:mime-version:content-transfer-encoding; bh=agTpXvCTTB9wh7DBugiS1SMOpvplNNTL1004RlqbTps=; b=izJ3o+JvJ2i146nzVs5zEPfzbavqxkU/QvBgc9xKPdqrU9yx1s3BMOuagNSHUEUm0O W1w30H5cn0PSsq3fRWDtoU/2O8yjywZM4YXUmHwOFh5Eju/hDkeeolT/zSn+uRjtmmHE uyBjounwpZaLo2hS0WiSKfdn7CNgDxT7fL9VNpgXIgQU0ONyEH6A6mK8JiAOAQiuPhTE 6fS6SdYUvO92/9XBz/WfwfDAYy60iKgxvOxrijodKeWKBn1CT5bcNZx9+vYeoNJKAPtu Wz31JzRCZB/FPAydaamffOy7pObzlLwOx6FFGSPUJwa76S2YeVc93Vak7dUUBntGTK3S 9eSQ== X-Gm-Message-State: APjAAAXYTYj45vu1s8i3yIKnGmCgzprOGB8LntVaYyzjBd6ITk0fgj9E 1bjj8+mPjh1/OvuwKsYieJ4Paw== X-Google-Smtp-Source: APXvYqyG8NF0G6wNd0iIRzjhDcom/LjD5zyhDumJ/RKSURlt36qy6yWJgAGhMn4cjRcy2Qss5VhtRQ== X-Received: by 2002:a63:3c47:: with SMTP id i7mr19600231pgn.237.1571637266080; Sun, 20 Oct 2019 22:54:26 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id s14sm13477263pfe.52.2019.10.20.22.54.25 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:25 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 09/18] Revert "Input: cros_ec_keyb: mask out extra flags in event_type" Date: Sun, 20 Oct 2019 22:53:54 -0700 Message-Id: <20191021055403.67849-10-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org This reverts commit d096aa3eb6045a6a475a0239f3471c59eedf3d61. This patch is not needed anymore since we clear EC_MKBP_HAS_MORE_EVENTS flag before calling the notifiers in patch "9d9518f5b52a (platform: chrome: cros_ec: handle MKBP more events flag)" Signed-off-by: Gwendal Grignou --- New to v2. drivers/input/keyboard/cros_ec_keyb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index a29e81fdf1861..2b71c5a51f907 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -237,7 +237,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb, if (queued_during_suspend && !device_may_wakeup(ckdev->dev)) return NOTIFY_OK; - switch (ckdev->ec->event_data.event_type & EC_MKBP_EVENT_TYPE_MASK) { + switch (ckdev->ec->event_data.event_type) { case EC_MKBP_EVENT_KEY_MATRIX: pm_wakeup_event(ckdev->dev, 0); From patchwork Mon Oct 21 05:53:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201383 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 90BCE112B for ; Mon, 21 Oct 2019 05:55:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3F51A21479 for ; Mon, 21 Oct 2019 05:55:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="ca4lAVAT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727422AbfJUFzB (ORCPT ); Mon, 21 Oct 2019 01:55:01 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:34869 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726148AbfJUFy3 (ORCPT ); Mon, 21 Oct 2019 01:54:29 -0400 Received: by mail-pl1-f196.google.com with SMTP id c3so6080051plo.2 for ; Sun, 20 Oct 2019 22:54:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HWUPovaRgase0S0bQJwltYfqHWuxiTMjCVRY4t8y8B8=; b=ca4lAVATzPvrz+q0Ul8tWiM1fCBFDKuXZ/WejbPFiTiqubTEdMaHo+hxmalzZooaH7 IaHYMy5CLVMi1OXwzkxCX60IknY52cu/gwXJS9hELpLvfX+8+zC5PYJMsZSi7G/KGB7P Hpd9kMmDM0exQEjPQ+vpLZXxvs8kbBgkHMMGM= 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:mime-version:content-transfer-encoding; bh=HWUPovaRgase0S0bQJwltYfqHWuxiTMjCVRY4t8y8B8=; b=M8EEIlQIUjEt7hK8t7iRlwcKmmkCNO36PmyxtNe2zbajaBD7XQuD9G3EF4r7mpamsD NhWDqUdvRlMrxYKYoM6R0nSYv/E+39ESqlZkQ9eom7D5r+KWfuPU7+7YO0CMp6GPp2Vw yWhv9B0qzmu7e2codQs/cfQVeAt1zQnce3V8R+/3H0jSpuzc3eZzoyfPt73dGPIbOsvS 2sYU+Q2tIJu9529jrh/Nj3WBwez4GaREOzwRsaRpi8ZunOD5ukeFqsKtDf/6Y7WzhqUg EtXYmOihOQtkSnkXBND1d8knALKxr9vH24T20sqBXSJbeZEFd4fegjFjgOrcKz5jL0CV Mkxw== X-Gm-Message-State: APjAAAUIDkZ65JkJymH7DVl+A00KTXsmxPw/Wj8jdfLqVqR+Gx+Xa9Gp HFaYodUgKCEg6EqzhEOBOhzDew== X-Google-Smtp-Source: APXvYqxlx+cdZ1aXujGfTIBiBQCuPVw7R94OCSHzf1LYpHrV/oBuoc43QNopi/E67XVglsY5GZ6VCw== X-Received: by 2002:a17:902:322:: with SMTP id 31mr3474315pld.293.1571637267456; Sun, 20 Oct 2019 22:54:27 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id i74sm18473401pfe.28.2019.10.20.22.54.26 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:26 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 10/18] platform: chrome: sensorhub: Add FIFO support Date: Sun, 20 Oct 2019 22:53:55 -0700 Message-Id: <20191021055403.67849-11-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org cros_ec_sensorhub registers a listener and query motion sense FIFO, spread to iio sensors registers. To test, we can use libiio: iiod& iio_readdev -u ip:localhost -T 10000 -s 25 -b 16 cros-ec-gyro | od -x Signed-off-by: Gwendal Grignou --- Changes sunce v2: - Do not register a .remove routinge in plaform_driver. A devm_action_add is added later patch IIO driver register their callback. - Remove double lines, add lines before return calls. - Handle FLUSH flag from EC. - Use ktime_t for most timestamp measurements. - Add doxygen comments - Cleanup timestamp collection when processing FIFO. - Rename fifo_toggle to fifo_enable drivers/platform/chrome/Makefile | 3 +- drivers/platform/chrome/cros_ec_sensorhub.c | 123 ++++-- .../platform/chrome/cros_ec_sensorhub_ring.c | 412 ++++++++++++++++++ .../linux/platform_data/cros_ec_sensorhub.h | 77 ++++ 4 files changed, 583 insertions(+), 32 deletions(-) create mode 100644 drivers/platform/chrome/cros_ec_sensorhub_ring.c diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index a164c40dc0996..cb709048c003e 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -17,7 +17,8 @@ obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.o obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o -obj-$(CONFIG_CROS_EC_SENSORHUB) += cros_ec_sensorhub.o +cros_ec_sensorsupport-objs := cros_ec_sensorhub_ring.o cros_ec_sensorhub.o +obj-$(CONFIG_CROS_EC_SENSORHUB) += cros_ec_sensorsupport.o obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c b/drivers/platform/chrome/cros_ec_sensorhub.c index 5fea4c28c5c95..87308dadc32c5 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub.c +++ b/drivers/platform/chrome/cros_ec_sensorhub.c @@ -24,7 +24,6 @@ #define DRV_NAME "cros-ec-sensorhub" - static struct device_type cros_ec_sensorhub_dev_type = { .name = "cros_ec_iio_sensor", }; @@ -64,14 +63,13 @@ static int cros_ec_sensorhub_allocate_single_sensor( } static int cros_ec_sensorhub_register(struct device *dev, - struct cros_ec_dev *ec) + struct cros_ec_sensorhub *sensorhub) { int ret, i, id, sensor_num; int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 }; - struct ec_params_motion_sense *params; - struct ec_response_motion_sense *resp; - struct cros_ec_command *msg; char *name; + struct cros_ec_command *msg = sensorhub->msg; + struct cros_ec_dev *ec = sensorhub->ec; sensor_num = cros_ec_get_sensor_count(ec); if (sensor_num < 0) { @@ -86,32 +84,21 @@ static int cros_ec_sensorhub_register(struct device *dev, return -EINVAL; } - /* Prepare a message to send INFO command to each sensor. */ - msg = kzalloc(sizeof(struct cros_ec_command) + - max(sizeof(*params), sizeof(*resp)), GFP_KERNEL); - if (!msg) { - ret = -ENOMEM; - goto error; - } - msg->version = 1; - msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; - msg->outsize = sizeof(*params); - msg->insize = sizeof(*resp); - params = (struct ec_params_motion_sense *)msg->data; - resp = (struct ec_response_motion_sense *)msg->data; + msg->insize = sizeof(struct ec_response_motion_sense); + msg->outsize = sizeof(struct ec_params_motion_sense); id = 0; for (i = 0; i < sensor_num; i++) { - params->cmd = MOTIONSENSE_CMD_INFO; - params->info.sensor_num = i; + sensorhub->params->cmd = MOTIONSENSE_CMD_INFO; + sensorhub->params->info.sensor_num = i; ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) { dev_warn(dev, "no info for EC sensor %d : %d/%d\n", i, ret, msg->result); continue; } - switch (resp->info.type) { + switch (sensorhub->resp->info.type) { case MOTIONSENSE_TYPE_ACCEL: name = "cros-ec-accel"; break; @@ -134,14 +121,15 @@ static int cros_ec_sensorhub_register(struct device *dev, name = "cros-ec-activity"; break; default: - dev_warn(dev, "unknown type %d\n", resp->info.type); + dev_warn(dev, "unknown type %d\n", + sensorhub->resp->info.type); continue; } ret = cros_ec_sensorhub_allocate_single_sensor(dev, name, i); if (ret) - goto error; + return ret; - sensor_type[resp->info.type]++; + sensor_type[sensorhub->resp->info.type]++; } if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) @@ -152,9 +140,6 @@ static int cros_ec_sensorhub_register(struct device *dev, ret = cros_ec_sensorhub_allocate_single_sensor( dev, "cros-ec-lid-angle", 0); } - -error: - kfree(msg); return ret; } @@ -163,34 +148,110 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); int ret; - struct cros_ec_sensorhub *data = - kzalloc(sizeof(struct cros_ec_sensorhub), GFP_KERNEL); + struct cros_ec_sensorhub *data; + struct cros_ec_command *msg; + msg = devm_kzalloc(dev, sizeof(struct cros_ec_command) + + max((u16)sizeof(struct ec_params_motion_sense), + ec->ec_dev->max_response), GFP_KERNEL); + if (!msg) + return -ENOMEM; + msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; + + data = devm_kzalloc(dev, sizeof(struct cros_ec_sensorhub), GFP_KERNEL); if (!data) return -ENOMEM; + data->dev = dev; data->ec = ec; + + mutex_init(&data->cmd_lock); + data->msg = msg; + data->params = (struct ec_params_motion_sense *)msg->data; + data->resp = (struct ec_response_motion_sense *)msg->data; + dev_set_drvdata(dev, data); /* Check whether this EC is a sensor hub. */ if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE)) { - ret = cros_ec_sensorhub_register(dev, ec); + ret = cros_ec_sensorhub_register(dev, data); } else { ret = cros_ec_sensorhub_allocate_single_sensor( dev, "cros-ec-accel-legacy", 0); ret |= cros_ec_sensorhub_allocate_single_sensor( dev, "cros-ec-accel-legacy", 1); } - if (ret) + if (ret) { dev_err(dev, "failed to add EC sensors: error %d\n", ret); + return ret; + } + + /* + * If the EC does not have a FIFO, the sensors will query their data + * themselves via sysfs or a software trigger. + */ + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { + ret = cros_ec_sensorhub_ring_add(data); + /* + * The msg and its data is not under the control of the ring + * handler. + */ + } return ret; } +static int cros_ec_sensorhub_remove(struct platform_device *pdev) +{ + struct cros_ec_sensorhub *sensorhub = platform_get_drvdata(pdev); + struct cros_ec_dev *ec = sensorhub->ec; + + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) + cros_ec_sensorhub_ring_remove(sensorhub); + return 0; +} + +/* + * When the EC is suspending, we must stop sending interrupt, + * we may use the same interrupt line for waking up the device. + * Tell the EC to stop sending non-interrupt event on the iio ring. + */ +static int __maybe_unused cros_ec_ring_prepare(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct cros_ec_sensorhub *sensorhub = platform_get_drvdata(pdev); + struct cros_ec_dev *ec = sensorhub->ec; + + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) + return cros_ec_sensorhub_ring_fifo_enable(sensorhub, false); + return 0; +} + +static void __maybe_unused cros_ec_ring_complete(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct cros_ec_sensorhub *sensorhub = platform_get_drvdata(pdev); + struct cros_ec_dev *ec = sensorhub->ec; + + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) + cros_ec_sensorhub_ring_fifo_enable(sensorhub, true); +} + +#if CONFIG_PM_SLEEP +static const struct dev_pm_ops cros_ec_sensorhub_ring_pm_ops = { + .prepare = cros_ec_ring_prepare, + .complete = cros_ec_ring_complete +}; +#else +static const struct dev_pm_ops cros_ec_sensorhub_ring_pm_ops = { }; +#endif + static struct platform_driver cros_ec_sensorhub_driver = { .driver = { .name = DRV_NAME, + .pm = &cros_ec_sensorhub_ring_pm_ops, }, .probe = cros_ec_sensorhub_probe, + .remove = cros_ec_sensorhub_remove, }; module_platform_driver(cros_ec_sensorhub_driver); diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c new file mode 100644 index 0000000000000..caf4b02d5e345 --- /dev/null +++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * cros_ec_sensorhub_ring - Driver for Chrome OS EC Sensor hub FIFO. + * + * Copyright 2019 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline int cros_sensorhub_send_sample( + struct cros_ec_sensorhub *sensorhub, + struct cros_ec_sensors_ring_sample *sample) +{ + int id = sample->sensor_id; + cros_ec_sensorhub_push_data_cb_t cb; + struct iio_dev *indio_dev; + + if (id > CROS_EC_SENSOR_MAX) + return -EINVAL; + + cb = sensorhub->push_data[id].push_data_cb; + if (!cb) + return 0; + + indio_dev = sensorhub->push_data[id].indio_dev; + + if (sample->flag & MOTIONSENSE_SENSOR_FLAG_FLUSH) + return 0; + + return cb(indio_dev, sample->vector, sample->timestamp); +} + +/** + * Function to register the callback to the sensor hub. + * The callback cb will be used by cros_ec_sensorhub_ring to distribute events + * from the EC. + * @sensor_hub : Sensor Hub object + * @sensor_num : The sensor the caller is interested in. + * @indio_dev : The iio device to use when a sample arrives. + * @cb : The callback to call when a sample arrives. + */ +int cros_ec_sensorhub_register_push_data( + struct cros_ec_sensorhub *sensorhub, + u8 sensor_num, + struct iio_dev *indio_dev, + cros_ec_sensorhub_push_data_cb_t cb) +{ + if (sensor_num > CROS_EC_SENSOR_MAX) + return -EINVAL; + if (sensorhub->push_data[sensor_num].indio_dev != NULL) + return -EINVAL; + + sensorhub->push_data[sensor_num].indio_dev = indio_dev; + sensorhub->push_data[sensor_num].push_data_cb = cb; + + return 0; +} +EXPORT_SYMBOL_GPL(cros_ec_sensorhub_register_push_data); + +void cros_ec_sensorhub_unregister_push_data( + struct cros_ec_sensorhub *sensorhub, + u8 sensor_num) +{ + sensorhub->push_data[sensor_num].indio_dev = NULL; + sensorhub->push_data[sensor_num].push_data_cb = NULL; +} +EXPORT_SYMBOL_GPL(cros_ec_sensorhub_unregister_push_data); + +/** + * Enable or disable interrupt generation for FIFO events. + * To be called before sleeping or when noone is listening. + * @sensor_hub : Sensor Hub object + * @on : true when events are requested. + */ +int cros_ec_sensorhub_ring_fifo_enable( + struct cros_ec_sensorhub *sensorhub, + bool on) +{ + int ret; + + mutex_lock(&sensorhub->cmd_lock); + sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INT_ENABLE; + sensorhub->params->fifo_int_enable.enable = on; + + sensorhub->msg->outsize = sizeof(struct ec_params_motion_sense); + sensorhub->msg->insize = sizeof(struct ec_response_motion_sense); + + ret = cros_ec_cmd_xfer_status(sensorhub->ec->ec_dev, sensorhub->msg); + /* We expect to receive a payload of 4 bytes, ignore. */ + if (ret > 0) + ret = 0; + mutex_unlock(&sensorhub->cmd_lock); + + return ret; +} + +/** + * cros_ec_ring_process_event: process one EC FIFO event + * + * Process one EC event, add it in the ring if necessary. + * + * @sensorhub: Sensorhub object. + * @fifo_info: fifo information from the EC (includes b point, EC timebase). + * @fifo_timestamp: EC IRQ, kernel timebase (aka c) + * @current_timestamp: calculated event timestamp, kernel timebase (aka a') + * @in: incoming FIFO event from EC (includes a point, EC timebase) + * @out: outgoing event to user space (includes a') + * + * Return true if out event has been populated. + */ +static bool cros_ec_ring_process_event( + struct cros_ec_sensorhub *sensorhub, + const struct cros_ec_fifo_info *fifo_info, + const ktime_t fifo_timestamp, + ktime_t *current_timestamp, + struct ec_response_motion_sensor_data *in, + struct cros_ec_sensors_ring_sample *out) +{ + int axis; + /* Do not populate the filter based on asynchronous events. */ + const int async_flags = in->flags & + (MOTIONSENSE_SENSOR_FLAG_ODR | MOTIONSENSE_SENSOR_FLAG_FLUSH); + const s64 now = cros_ec_get_time_ns(); + + if (in->flags & MOTIONSENSE_SENSOR_FLAG_TIMESTAMP && !async_flags) { + s64 a = in->timestamp; + s64 b = fifo_info->info.timestamp; + s64 c = fifo_timestamp; + s64 new_timestamp; + + /* + * disable filtering since we might add more jitter + * if b is in a random point in time + */ + new_timestamp = c - b * 1000 + a * 1000; + + /* + * The timestamp can be stale if we had to use the fifo + * info timestamp. + */ + if (new_timestamp - *current_timestamp > 0) + *current_timestamp = new_timestamp; + } + + if (in->flags & MOTIONSENSE_SENSOR_FLAG_FLUSH) { + out->sensor_id = in->sensor_num; + out->timestamp = *current_timestamp; + out->flag = in->flags; + /* + * No other payload information provided with + * flush ack. + */ + return true; + } + if (in->flags & MOTIONSENSE_SENSOR_FLAG_TIMESTAMP) + /* If we just have a timestamp, skip this entry. */ + return false; + + /* Regular sample */ + out->sensor_id = in->sensor_num; + if (*current_timestamp - now > 0) { + /* If the timestamp is in the future. */ + out->timestamp = now; + } else { + out->timestamp = *current_timestamp; + } + + out->flag = in->flags; + for (axis = 0; axis < 3; axis++) + out->vector[axis] = in->data[axis]; + + return true; +} + +/* + * cros_ec_sensorhub_ring_handler - the trigger handler function + * + * @sensorhub: device information. + * + * Called by the notifier, process the EC sensor FIFO queue. + */ +static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub) +{ + struct cros_ec_fifo_info *fifo_info = &sensorhub->fifo_info; + struct cros_ec_dev *ec = sensorhub->ec; + ktime_t fifo_timestamp, current_timestamp; + int i, j, number_data, ret; + unsigned long sensor_mask = 0; + struct ec_response_motion_sensor_data *in; + struct cros_ec_sensors_ring_sample *out, *last_out; + + mutex_lock(&sensorhub->cmd_lock); + + /* Get FIFO information if there are lost vectors. */ + if (fifo_info->info.total_lost) { + /* Need to retrieve the number of lost vectors per sensor */ + sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INFO; + sensorhub->msg->outsize = 1; + sensorhub->msg->insize = + sizeof(struct ec_response_motion_sense_fifo_info) + + sizeof(u16) * CROS_EC_SENSOR_MAX; + + if (cros_ec_cmd_xfer_status(ec->ec_dev, sensorhub->msg) < 0) { + mutex_unlock(&sensorhub->cmd_lock); + return; + } + memcpy(fifo_info, &sensorhub->resp->fifo_info, + sizeof(*fifo_info)); + + /* + * Update collection time, will not be as precise as the + * non-error case. + */ + fifo_timestamp = cros_ec_get_time_ns(); + } else { + fifo_timestamp = sensorhub->fifo_timestamp[ + CROS_EC_SENSOR_NEW_TS]; + } + + if (fifo_info->info.count > sensorhub->fifo_size || + fifo_info->info.size != sensorhub->fifo_size) { + dev_warn(sensorhub->dev, + "Mismatch EC data: count %d, size %d - expected %d", + fifo_info->info.count, fifo_info->info.size, + sensorhub->fifo_size); + mutex_unlock(&sensorhub->cmd_lock); + return; + } + + + /* Copy elements in the main fifo */ + current_timestamp = sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS]; + out = sensorhub->ring; + for (i = 0; i < fifo_info->info.count; i += number_data) { + sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_READ; + sensorhub->params->fifo_read.max_data_vector = + fifo_info->info.count - i; + sensorhub->msg->outsize = + sizeof(struct ec_params_motion_sense); + sensorhub->msg->insize = + sizeof(sensorhub->resp->fifo_read) + + sensorhub->params->fifo_read.max_data_vector * + sizeof(struct ec_response_motion_sensor_data); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, sensorhub->msg); + if (ret < 0) { + dev_warn(sensorhub->dev, "Fifo error: %d\n", ret); + break; + } + number_data = sensorhub->resp->fifo_read.number_data; + if (number_data == 0) { + dev_dbg(sensorhub->dev, "Unexpected empty FIFO\n"); + break; + } + if (number_data > fifo_info->info.count - i) { + dev_warn(sensorhub->dev, + "Invalid EC data: too many entry received: %d, expected %d", + number_data, fifo_info->info.count - i); + break; + } + if (out + number_data > + sensorhub->ring + fifo_info->info.count) { + dev_warn(sensorhub->dev, + "Too many samples: %d (%zd data) to %d entries for expected %d entries", + i, out - sensorhub->ring, i + number_data, + fifo_info->info.count); + break; + } + + for (in = sensorhub->resp->fifo_read.data, j = 0; + j < number_data; j++, in++) { + if (cros_ec_ring_process_event( + sensorhub, fifo_info, fifo_timestamp, + ¤t_timestamp, in, out)) { + sensor_mask |= (1 << in->sensor_num); + out++; + } + } + } + mutex_unlock(&sensorhub->cmd_lock); + last_out = out; + + if (out == sensorhub->ring) + /* Unexpected empty FIFO. */ + goto ring_handler_end; + + /* + * Check if current_timestamp is ahead of the last sample. + * Normally, the EC appends a timestamp after the last sample, but if + * the AP is slow to respond to the IRQ, the EC may have added new + * samples. Use the FIFO info timestamp as last timestamp then. + */ + if ((last_out-1)->timestamp == current_timestamp) + current_timestamp = fifo_timestamp; + + /* Warn on lost samples. */ + for_each_set_bit(i, &sensor_mask, BITS_PER_LONG) { + if (fifo_info->info.total_lost) { + int lost = fifo_info->lost[i]; + + if (lost) { + dev_warn_ratelimited(sensorhub->dev, + "Sensor %d: lost: %d out of %d\n", i, + lost, fifo_info->info.total_lost); + } + } + } + + /* push the event into the kfifo */ + for (out = sensorhub->ring; out < last_out; out++) + cros_sensorhub_send_sample(sensorhub, out); + +ring_handler_end: + sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] = current_timestamp; +} + +static int cros_ec_sensorhub_event(struct notifier_block *nb, + unsigned long queued_during_suspend, void *_notify) +{ + struct cros_ec_sensorhub *sensorhub; + struct cros_ec_device *ec_dev; + + sensorhub = container_of(nb, struct cros_ec_sensorhub, notifier); + ec_dev = sensorhub->ec->ec_dev; + + if (ec_dev->event_data.event_type != EC_MKBP_EVENT_SENSOR_FIFO) + return NOTIFY_DONE; + + if (ec_dev->event_size != sizeof(ec_dev->event_data.data.sensor_fifo)) { + dev_warn(ec_dev->dev, "Invalid fifo info size\n"); + return NOTIFY_DONE; + } + + if (queued_during_suspend) + return NOTIFY_OK; + + sensorhub->fifo_info.info = ec_dev->event_data.data.sensor_fifo.info; + sensorhub->fifo_timestamp[CROS_EC_SENSOR_NEW_TS] = + ec_dev->last_event_time; + cros_ec_sensorhub_ring_handler(sensorhub); + + return NOTIFY_OK; +} + +/** + * Add/Remove the fifo functionality if the EC supports it. + * @sensor_hub : Sensor Hub object + */ +int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) +{ + struct cros_ec_dev *ec = sensorhub->ec; + int ret; + + /* Retrieve FIFO information */ + sensorhub->msg->version = 2; + sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INFO; + sensorhub->msg->outsize = 1; + sensorhub->msg->insize = + sizeof(struct ec_response_motion_sense_fifo_info) + + sizeof(u16) * CROS_EC_SENSOR_MAX; + + ret = cros_ec_cmd_xfer_status(ec->ec_dev, sensorhub->msg); + if (ret < 0) + return ret; + + /* + * Allocate the full fifo. + * We need to copy the whole FIFO to set timestamps properly * + */ + sensorhub->fifo_size = sensorhub->resp->fifo_info.size; + sensorhub->ring = devm_kcalloc(sensorhub->dev, sensorhub->fifo_size, + sizeof(*sensorhub->ring), GFP_KERNEL); + if (!sensorhub->ring) + return -ENOMEM; + + sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] = + cros_ec_get_time_ns(); + + /* register the notifier that will act as a top half interrupt. */ + sensorhub->notifier.notifier_call = cros_ec_sensorhub_event; + ret = blocking_notifier_chain_register(&ec->ec_dev->event_notifier, + &sensorhub->notifier); + if (ret < 0) { + dev_warn(sensorhub->dev, "failed to register notifier\n"); + return ret; + } + + /* Start collection samples. */ + return cros_ec_sensorhub_ring_fifo_enable(sensorhub, true); +} + +int cros_ec_sensorhub_ring_remove(struct cros_ec_sensorhub *sensorhub) +{ + struct cros_ec_device *ec_dev = sensorhub->ec->ec_dev; + + /* Disable the ring, prevent EC interrupt to the AP for nothing. */ + cros_ec_sensorhub_ring_fifo_enable(sensorhub, false); + blocking_notifier_chain_unregister(&ec_dev->event_notifier, + &sensorhub->notifier); + + return 0; +} diff --git a/include/linux/platform_data/cros_ec_sensorhub.h b/include/linux/platform_data/cros_ec_sensorhub.h index c18fba660bb62..595d010b58d95 100644 --- a/include/linux/platform_data/cros_ec_sensorhub.h +++ b/include/linux/platform_data/cros_ec_sensorhub.h @@ -8,6 +8,7 @@ #ifndef __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H #define __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H +#include #include /** @@ -18,12 +19,88 @@ struct cros_ec_sensor_platform { u8 sensor_num; }; +/** + * Callback function to send datum to specific sensors. + * @indio_dev: The IIO device that will process the sample. + * @data: vector array of the ring sample. + * @timestamp: Timestamp in host timespace when the sample was acquired by + * the EC. + */ +typedef int (*cros_ec_sensorhub_push_data_cb_t)( + struct iio_dev *indio_dev, + s16 *data, + s64 timestamp); + +struct cros_ec_sensorhub_sensor_push_data { + struct iio_dev *indio_dev; + cros_ec_sensorhub_push_data_cb_t push_data_cb; +}; + +enum { + CROS_EC_SENSOR_LAST_TS, + CROS_EC_SENSOR_NEW_TS, + CROS_EC_SENSOR_ALL_TS +}; + +#define CROS_EC_SENSOR_MAX 16 + +struct __ec_todo_packed cros_ec_fifo_info { + struct ec_response_motion_sense_fifo_info info; + uint16_t lost[CROS_EC_SENSOR_MAX]; +}; + +struct cros_ec_sensors_ring_sample { + uint8_t sensor_id; + uint8_t flag; + int16_t vector[3]; + s64 timestamp; +} __packed; + /* * struct cros_ec_sensorhub - Sensor Hub device data. */ struct cros_ec_sensorhub { + /* Device object, mostly used for logging. */ + struct device *dev; + /* Embedded Controller where the hub is located. */ struct cros_ec_dev *ec; + + /* Structure to send FIFO requests. */ + struct cros_ec_command *msg; + struct ec_params_motion_sense *params; + struct ec_response_motion_sense *resp; + struct mutex cmd_lock; + + /* Notifier to kick the FIFO interrupt */ + struct notifier_block notifier; + + /* Preprocessed ring to send to kfifos */ + struct cros_ec_sensors_ring_sample *ring; + + ktime_t fifo_timestamp[CROS_EC_SENSOR_ALL_TS]; + struct cros_ec_fifo_info fifo_info; + int fifo_size; + + /* + * Dynamic array to be able to spread datum to iio sensor objects. + */ + struct cros_ec_sensorhub_sensor_push_data push_data[CROS_EC_SENSOR_MAX]; }; +int cros_ec_sensorhub_register_push_data( + struct cros_ec_sensorhub *sensor_hub, + u8 sensor_num, + struct iio_dev *indio_dev, + cros_ec_sensorhub_push_data_cb_t cb); +void cros_ec_sensorhub_unregister_push_data( + struct cros_ec_sensorhub *sensor_hub, + u8 sensor_num); + +int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensor_hub); +int cros_ec_sensorhub_ring_remove(struct cros_ec_sensorhub *sensor_hub); +int cros_ec_sensorhub_ring_fifo_enable( + struct cros_ec_sensorhub *sensorhub, + bool on); + #endif /* __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H */ From patchwork Mon Oct 21 05:53:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201385 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 43ECD1575 for ; Mon, 21 Oct 2019 05:55:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 19BFF21479 for ; Mon, 21 Oct 2019 05:55:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="J69/Hg+E" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727419AbfJUFzA (ORCPT ); Mon, 21 Oct 2019 01:55:00 -0400 Received: from mail-pf1-f195.google.com ([209.85.210.195]:37897 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727290AbfJUFya (ORCPT ); Mon, 21 Oct 2019 01:54:30 -0400 Received: by mail-pf1-f195.google.com with SMTP id h195so7692732pfe.5 for ; Sun, 20 Oct 2019 22:54:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=EP/9iLKiNwr5MLu9Z4HlI82XvD91cPcV9WXTeaSAUo0=; b=J69/Hg+EhtvPLU/f+pvHj6fxwllFXnCc+zZvtzYbfI6ppakwiG8QF67WpbtFPja6UG rL3O2cUZ+WFyV5WC6VXQAKiMD5S1pk0jMv0pxkexhaUI9QDVAYnc6echyFUMfmqXt7VH pjW9POED9x3YOm3oNduW1Nz4ShyLgnmJ0sofM= 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:mime-version:content-transfer-encoding; bh=EP/9iLKiNwr5MLu9Z4HlI82XvD91cPcV9WXTeaSAUo0=; b=mmolUgZZu5VYQh4jaX+Gb93zM6AjJPRPUilZTxKEPUUrCvNIfqt90O8RbSzm/Uer1U MqdFmWX5phz3GW/cGJcSPuAuslxau5l5kS0mdokkwwnvK9i3LYeiG1g1ipYQwuwcUb9w HmEI2kOS9twUAS0eEjT1aQ2z53ZGKOVFyhvvLIrD0ftkW6rfeizl1WoljOHzIgLJeFug AEGxW4+Ui3ae1s3pOrD2759gr9EsH49WG0or2wsPKkCmxD7veCDWY8Mnpa2nifp3dF2y /UhPM7DDlcDw7Mca9MlLgGHGJW8eLYloBlsezdSwDupuFiXBOsYO2c+wq4ElszQbFrfa dkYw== X-Gm-Message-State: APjAAAWKrbWgen2Yt5VUfkyUwFkTjUGE6F48CuYbsSU1NfHX3+eTcE99 p/MzFf41t1RcwKK7kcFLsGkJeQ== X-Google-Smtp-Source: APXvYqxMhdpnivWEC0h+sdQZgH8IaEfCAZ9mMzPo0Zls/MJNxJiyPV01qSiHd9JomCl5XEoFck5+hw== X-Received: by 2002:a17:90a:bd8e:: with SMTP id z14mr25800971pjr.40.1571637269213; Sun, 20 Oct 2019 22:54:29 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id c7sm13029553pfr.75.2019.10.20.22.54.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:28 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 11/18] platform: chrome: sensorhub: Add code to spread timestmap Date: Sun, 20 Oct 2019 22:53:56 -0700 Message-Id: <20191021055403.67849-12-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org EC FIFO can send sensor events in batch. Spread them based on previous (TSa) and currnet timestamp (TSb) EC FIFO iio events +-----------+ | TSa | +-----------+ +---------------------------------------+ | event 1 | | event 1 | TSb - (TSb - TSa)/n * (n-1) | +-----------+ +---------------------------------------+ | event 2 | | event 2 | TSb - (TSb - TSa)/n * (n-2) | +-----------+ +---------------------------------------+ | ... | ------> | .... | | +-----------+ +---------------------------------------+ | event n-1 | | event 2 | TSb - (TSb - TSa)/n | +-----------+ +---------------------------------------+ | event n | | event 2 | TSb | +-----------+ +---------------------------------------+ | TSb | +-----------+ Signed-off-by: Gwendal Grignou --- Changes in v2: - Use CROS_EC_SENSOR_LAST_TS instead of LAST_TS to avoid name colisions. .../platform/chrome/cros_ec_sensorhub_ring.c | 99 ++++++++++++++++++- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c index caf4b02d5e345..0b851ac7c067e 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c +++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c @@ -183,6 +183,97 @@ static bool cros_ec_ring_process_event( return true; } +/* + * cros_ec_ring_spread_add: Calculate proper timestamps then + * add to ringbuffer (legacy). + * + * If there is a sample with a proper timestamp + * timestamp | count + * older_unprocess_out --> TS1 | 1 + * TS1 | 2 + * out --> TS1 | 3 + * next_out --> TS2 | + * We spread time for the samples [older_unprocess_out .. out] + * between TS1 and TS2: [TS1+1/4, TS1+2/4, TS1+3/4, TS2]. + * + * If we reach the end of the samples, we compare with the + * current timestamp: + * + * older_unprocess_out --> TS1 | 1 + * TS1 | 2 + * out --> TS1 | 3 + * We know have [TS1+1/3, TS1+2/3, current timestamp] + */ +static void cros_ec_ring_spread_add( + struct cros_ec_sensorhub *sensorhub, + unsigned long sensor_mask, + s64 current_timestamp, + struct cros_ec_sensors_ring_sample *last_out) +{ + struct cros_ec_sensors_ring_sample *out; + int i; + + for_each_set_bit(i, &sensor_mask, BITS_PER_LONG) { + s64 older_timestamp; + s64 timestamp; + struct cros_ec_sensors_ring_sample *older_unprocess_out = + sensorhub->ring; + struct cros_ec_sensors_ring_sample *next_out; + int count = 1; + + for (out = sensorhub->ring; out < last_out; out = next_out) { + s64 time_period; + + next_out = out + 1; + if (out->sensor_id != i) + continue; + + /* Timestamp to start with */ + older_timestamp = out->timestamp; + + /* find next sample */ + while (next_out < last_out && next_out->sensor_id != i) + next_out++; + + if (next_out >= last_out) { + timestamp = current_timestamp; + } else { + timestamp = next_out->timestamp; + if (timestamp == older_timestamp) { + count++; + continue; + } + } + + /* + * The next sample has a new timestamp, + * spread the unprocessed samples. + */ + if (next_out < last_out) + count++; + time_period = div_s64(timestamp - older_timestamp, + count); + + for (; older_unprocess_out <= out; + older_unprocess_out++) { + if (older_unprocess_out->sensor_id != i) + continue; + older_timestamp += time_period; + older_unprocess_out->timestamp = + older_timestamp; + } + count = 1; + /* The next_out sample has a valid timestamp, skip. */ + next_out++; + older_unprocess_out = next_out; + } + } + + /* push the event into the kfifo */ + for (out = sensorhub->ring; out < last_out; out++) + cros_sensorhub_send_sample(sensorhub, out); +} + /* * cros_ec_sensorhub_ring_handler - the trigger handler function * @@ -316,9 +407,11 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub) } } - /* push the event into the kfifo */ - for (out = sensorhub->ring; out < last_out; out++) - cros_sensorhub_send_sample(sensorhub, out); + /* + * Spread samples in case of batching, then add them to the ringbuffer. + */ + cros_ec_ring_spread_add(sensorhub, sensor_mask, + current_timestamp, last_out); ring_handler_end: sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] = current_timestamp; From patchwork Mon Oct 21 05:53:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201381 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 457C91575 for ; Mon, 21 Oct 2019 05:55:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 07A022089C for ; Mon, 21 Oct 2019 05:55:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="LfPr3Geu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727313AbfJUFyf (ORCPT ); Mon, 21 Oct 2019 01:54:35 -0400 Received: from mail-pg1-f193.google.com ([209.85.215.193]:38182 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726167AbfJUFye (ORCPT ); Mon, 21 Oct 2019 01:54:34 -0400 Received: by mail-pg1-f193.google.com with SMTP id w3so7074638pgt.5 for ; Sun, 20 Oct 2019 22:54:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=c95X2NS5xfdhH8jcZNIOPmeDlbGpQbkNH5blBmTfiWQ=; b=LfPr3Geuo6efsZajtobP2dHWL2Ls/SOUsCGzWsKg/mnGDGaeHTiTqaad/aTVthU4br XxMRU56ovdo2alcPB4W9DNf1ZL9qI4V01FshF7HZxQEEI7EWpNLW4/74/6x1ukBmA9ph ZkT11RH8ylzFnTMy6aha727DcV2zipD2ZJw38= 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:mime-version:content-transfer-encoding; bh=c95X2NS5xfdhH8jcZNIOPmeDlbGpQbkNH5blBmTfiWQ=; b=oVN4zAqyZwLkqBe1yQR5yRZig2kjQiTtHKN4pC7JDTAVHP1KtI3rFd1a9KL1/myADe UsNZl9AK844B0oGxbIOGykteee/tGsyQyIuKQompo9Vs1tSjpQyUngd58Db3KLRrocZJ BBtz8Mg7icQ1N9Cg31sZkFzOxabHtP7hrdEdUr8n+Rg3jCiJasveyXiXjk0tPm1TrlzZ DaIZC5fFcWlHPd2pUKTR+sJ9OzpTw4UHG+dmoPWzK0HQmX7NOEXKA/U+XlTF+Pkj7QDL aF3dtl0l3kJs4Y/62l6p308x8h79BTKshna3qxt+UiauPW0oae7moBjvzlyxEfk+v9+v HPZQ== X-Gm-Message-State: APjAAAWFeNTl1BbH0qHzTXpO1c+NVMEOa6ahNi+nnn4FBkb6jipKwMix q3deWkQ7tPtct4HTPDVCMChcKQ== X-Google-Smtp-Source: APXvYqyCzWwzQ8goyUBeItdFoqXgEcmyOA9OdgcGU22lI47M4Z88nbQR6Oqys8DXD5uvxLSiqBWHnw== X-Received: by 2002:a17:90a:3702:: with SMTP id u2mr26876881pjb.57.1571637271071; Sun, 20 Oct 2019 22:54:31 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id ce16sm13757368pjb.29.2019.10.20.22.54.30 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:30 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 12/18] platform: chrome: sensorhub: Add median filter Date: Sun, 20 Oct 2019 22:53:57 -0700 Message-Id: <20191021055403.67849-13-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Events are timestamped in EC time space, their timestamps need to be converted in host time space. The assumption is the time delta between when the interrupt is sent by the EC and when it is receive by the host is a [small] constant. This is not always true, even with hard-wired interrupt. To mitigate worst offenders, add a median filter to weed out bigger than expected delays. Signed-off-by: Gwendal Grignou --- Changes in v2: - Move some #define in .c to prevent name collisions. - Add proper doxygen comments. - Use /* instead of // .../platform/chrome/cros_ec_sensorhub_ring.c | 504 +++++++++++++++++- .../linux/platform_data/cros_ec_sensorhub.h | 65 +++ 2 files changed, 551 insertions(+), 18 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c index 0b851ac7c067e..090773af70f48 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c +++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c @@ -18,6 +18,21 @@ #include #include +/* Precision of fixed point for the m values from the filter */ +#define M_PRECISION (1 << 23) + +/* Only activate the filter once we have at least this many elements. */ +#define TS_HISTORY_THRESHOLD 8 + +/* + * If we don't have any history entries for this long, empty the filter to + * make sure there are no big discontinuities. + */ +#define TS_HISTORY_BORED_US 500000 + +/* To measure by how much the filter is overshooting, if it happens. */ +#define FUTURE_TS_ANALYTICS_COUNT_MAX 100 + static inline int cros_sensorhub_send_sample( struct cros_ec_sensorhub *sensorhub, struct cros_ec_sensors_ring_sample *sample) @@ -87,9 +102,11 @@ int cros_ec_sensorhub_ring_fifo_enable( struct cros_ec_sensorhub *sensorhub, bool on) { - int ret; + int ret, i; mutex_lock(&sensorhub->cmd_lock); + for (i = 0; i < CROS_EC_SENSOR_MAX; i++) + sensorhub->last_batch_len[i] = 0; sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INT_ENABLE; sensorhub->params->fifo_int_enable.enable = on; @@ -105,6 +122,229 @@ int cros_ec_sensorhub_ring_fifo_enable( return ret; } +static int cros_ec_ring_median_cmp(const void *pv1, const void *pv2) +{ + s64 v1 = *(s64 *)pv1; + s64 v2 = *(s64 *)pv2; + + if (v1 > v2) + return 1; + else if (v1 < v2) + return -1; + else + return 0; +} + +/* + * cros_ec_ring_median: Gets median of an array of numbers + * + * For now it's implemented using an inefficient > O(n) sort then return + * the middle element. A more optimal method would be something like + * quickselect, but given that n = 64 we can probably live with it in the + * name of clarity. + * + * Warning: the input array gets modified (sorted)! + */ +static s64 cros_ec_ring_median(s64 *array, size_t length) +{ + sort(array, length, sizeof(s64), cros_ec_ring_median_cmp, NULL); + return array[length / 2]; +} + +/* + * IRQ Timestamp Filtering + * + * Lower down in cros_ec_ring_process_event(), for each sensor event we have to + * calculate it's timestamp in the AP timebase. There are 3 time points: + * a - EC timebase, sensor event + * b - EC timebase, IRQ + * c - AP timebase, IRQ + * a' - what we want: sensor even in AP timebase + * + * While a and b are recorded at accurate times (due to the EC real time + * nature); c is pretty untrustworthy, even though it's recorded the + * first thing in ec_irq_handler(). There is a very good change we'll get + * added lantency due to: + * other irqs + * ddrfreq + * cpuidle + * + * Normally a' = c - b + a, but if we do that naive math any jitter in c + * will get coupled in a', which we don't want. We want a function + * a' = cros_ec_ring_ts_filter(a) which will filter out outliers in c. + * + * Think of a graph of AP time(b) on the y axis vs EC time(c) on the x axis. + * The slope of the line won't be exactly 1, there will be some clock drift + * between the 2 chips for various reasons (mechanical stress, temperature, + * voltage). We need to extrapolate values for a future x, without trusting + * recent y values too much. + * + * We use a median filter for the slope, then another median filter for the + * y-intercept to calculate this function: + * dx[n] = x[n-1] - x[n] + * dy[n] = x[n-1] - x[n] + * m[n] = dy[n] / dx[n] + * median_m = median(m[n-k:n]) + * error[i] = y[n-i] - median_m * x[n-i] + * median_error = median(error[:k]) + * predicted_y = median_m * x + median_error + * + * Implementation differences from above: + * - Redefined y to be actually c - b, this gives us a lot more precision + * to do the math. (c-b)/b variations are more obvious than c/b variations. + * - Since we don't have floating point, any operations involving slope are + * done using fixed point math (*M_PRECISION) + * - Since x and y grow with time, we keep zeroing the graph (relative to + * the last sample), this way math involving *x[n-i] will not overflow + * - EC timestamps are kept in us, it improves the slope calculation precision + */ + +/** + * cros_ec_ring_ts_filter_update: Given a new IRQ timestamp pair (EC and + * AP timebases), add it to the filter history. + * + * @state: Filter information. + * @b: IRQ timestamp, EC timebase (us) + * @c: IRQ timestamp, AP timebase (ns) + */ +static void cros_ec_ring_ts_filter_update( + struct cros_ec_sensors_ts_filter_state *state, + s64 b, s64 c) +{ + s64 x, y; + s64 dx, dy; + s64 m; /* stored as *M_PRECISION */ + s64 *m_history_copy = state->temp_buf; + s64 *error = state->temp_buf; + int i; + + /* we trust b the most, that'll be our independent variable */ + x = b; + /* y is the offset between AP and EC times, in ns */ + y = c - b * 1000; + + dx = (state->x_history[0] + state->x_offset) - x; + if (dx == 0) + return; /* we already have this irq in the history */ + dy = (state->y_history[0] + state->y_offset) - y; + m = div64_s64(dy * M_PRECISION, dx); + + /* Empty filter if we haven't seen any action in a while. */ + if (-dx > TS_HISTORY_BORED_US) + state->history_len = 0; + + /* Move everything over, also update offset to all absolute coords .*/ + for (i = state->history_len - 1; i >= 1; i--) { + state->x_history[i] = state->x_history[i-1] + dx; + state->y_history[i] = state->y_history[i-1] + dy; + + state->m_history[i] = state->m_history[i-1]; + /* + * Also use the same loop to copy m_history for future + * median extraction. + */ + m_history_copy[i] = state->m_history[i-1]; + } + + /* Store the x and y, but remember offset is actually last sample. */ + state->x_offset = x; + state->y_offset = y; + state->x_history[0] = 0; + state->y_history[0] = 0; + + state->m_history[0] = m; + m_history_copy[0] = m; + + if (state->history_len < CROS_EC_SENSORHUB_TS_HISTORY_SIZE) + state->history_len++; + + /* Precalculate things for the filter. */ + if (state->history_len > TS_HISTORY_THRESHOLD) { + state->median_m = + cros_ec_ring_median(m_history_copy, state->history_len - 1); + + /* + * Calculate y-intercepts as if m_median is the slope and + * points in the history are on the line. median_error will + * still be in the offset coordinate system. + */ + for (i = 0; i < state->history_len; i++) + error[i] = state->y_history[i] - + div_s64(state->median_m * state->x_history[i], + M_PRECISION); + state->median_error = + cros_ec_ring_median(error, state->history_len); + } else { + state->median_m = 0; + state->median_error = 0; + } +} + +/** + * cros_ec_ring_ts_filter: Translate EC timebase timestamp to AP timebase + * + * @state: filter information. + * @x: any ec timestamp (us): + * + * cros_ec_ring_ts_filter(a) => a' event timestamp, AP timebase + * cros_ec_ring_ts_filter(b) => calculated timestamp when the EC IRQ + * should have happened on the AP, with low jitter + * + * @returns timestamp in AP timebase (ns) + * + * Note: The filter will only activate once state->history_len goes + * over TS_HISTORY_THRESHOLD. Otherwise it'll just do the naive c - b + a + * transform. + * + * How to derive the formula, starting from: + * f(x) = median_m * x + median_error + * That's the calculated AP - EC offset (at the x point in time) + * Undo the coordinate system transform: + * f(x) = median_m * (x - x_offset) + median_error + y_offset + * Remember to undo the "y = c - b * 1000" modification: + * f(x) = median_m * (x - x_offset) + median_error + y_offset + x * 1000 + */ +static s64 cros_ec_ring_ts_filter(struct cros_ec_sensors_ts_filter_state *state, + s64 x) +{ + return div_s64(state->median_m * (x - state->x_offset), M_PRECISION) + + state->median_error + state->y_offset + x * 1000; +} + +/* + * Since a and b were originally 32 bit values from the EC, + * they overflow relatively often, casting is not enough, so we need to + * add an offset. + */ +static void cros_ec_ring_fix_overflow(s64 *ts, + const s64 overflow_period, + struct cros_ec_sensors_ec_overflow_state *state) +{ + s64 adjust; + + *ts += state->offset; + if (abs(state->last - *ts) > (overflow_period / 2)) { + adjust = state->last > *ts ? overflow_period : -overflow_period; + state->offset += adjust; + *ts += adjust; + } + state->last = *ts; +} + +static void cros_ec_ring_check_for_past_timestamp( + struct cros_ec_sensorhub *sensorhub, + struct cros_ec_sensors_ring_sample *sample) +{ + const u8 sensor_id = sample->sensor_id; + + /* If this event is earlier than one we saw before... */ + if (sensorhub->newest_sensor_event[sensor_id] > sample->timestamp) + /* mark it for spreading. */ + sample->timestamp = sensorhub->last_batch_timestamp[sensor_id]; + else + sensorhub->newest_sensor_event[sensor_id] = sample->timestamp; +} + /** * cros_ec_ring_process_event: process one EC FIFO event * @@ -137,32 +377,54 @@ static bool cros_ec_ring_process_event( s64 a = in->timestamp; s64 b = fifo_info->info.timestamp; s64 c = fifo_timestamp; - s64 new_timestamp; - /* - * disable filtering since we might add more jitter - * if b is in a random point in time - */ - new_timestamp = c - b * 1000 + a * 1000; + cros_ec_ring_fix_overflow(&a, 1LL << 32, + &sensorhub->overflow_a); + cros_ec_ring_fix_overflow(&b, 1LL << 32, + &sensorhub->overflow_b); + + if (sensorhub->tight_timestamps) { + cros_ec_ring_ts_filter_update(&sensorhub->filter, b, c); + *current_timestamp = + cros_ec_ring_ts_filter(&sensorhub->filter, a); + } else { + s64 new_timestamp; + /* + * disable filtering since we might add more jitter + * if b is in a random point in time + */ + new_timestamp = c - b * 1000 + a * 1000; + /* + * The timestamp can be stale if we had to use the fifo + * info timestamp. + */ + if (new_timestamp - *current_timestamp > 0) + *current_timestamp = new_timestamp; + } + } + if (in->flags & MOTIONSENSE_SENSOR_FLAG_ODR) { + sensorhub->last_batch_len[in->sensor_num] = + sensorhub->penultimate_batch_len[in->sensor_num] = 0; /* - * The timestamp can be stale if we had to use the fifo - * info timestamp. + * ODR change is only useful for the sensor_ring, it does not + * convey information to clients. */ - if (new_timestamp - *current_timestamp > 0) - *current_timestamp = new_timestamp; + return false; } if (in->flags & MOTIONSENSE_SENSOR_FLAG_FLUSH) { out->sensor_id = in->sensor_num; out->timestamp = *current_timestamp; out->flag = in->flags; + sensorhub->last_batch_len[out->sensor_id] = 0; /* * No other payload information provided with * flush ack. */ return true; } + if (in->flags & MOTIONSENSE_SENSOR_FLAG_TIMESTAMP) /* If we just have a timestamp, skip this entry. */ return false; @@ -170,7 +432,22 @@ static bool cros_ec_ring_process_event( /* Regular sample */ out->sensor_id = in->sensor_num; if (*current_timestamp - now > 0) { - /* If the timestamp is in the future. */ + /* + * This fix is needed to overcome the timestamp filter putting + * events in the future. + */ + sensorhub->future_timestamp_total_ns += + *current_timestamp - now; + if (++sensorhub->future_timestamp_count == + FUTURE_TS_ANALYTICS_COUNT_MAX) { + s64 avg = div_s64(sensorhub->future_timestamp_total_ns, + sensorhub->future_timestamp_count); + dev_warn(sensorhub->dev, + "100 timestamps in the future, %lldns shaved on average\n", + avg); + sensorhub->future_timestamp_count = 0; + sensorhub->future_timestamp_total_ns = 0; + } out->timestamp = now; } else { out->timestamp = *current_timestamp; @@ -180,13 +457,195 @@ static bool cros_ec_ring_process_event( for (axis = 0; axis < 3; axis++) out->vector[axis] = in->data[axis]; + if (sensorhub->tight_timestamps) + cros_ec_ring_check_for_past_timestamp(sensorhub, out); return true; } /* - * cros_ec_ring_spread_add: Calculate proper timestamps then + * cros_ec_ring_spread_add: Calculate proper timestamps then add to ringbuffer. + * + * Note: This is the new spreading code, assumes every sample's timestamp + * preceeds the sample. Run if tight_timestamps == true. + * + * Sometimes the EC receives only one interrupt (hence timestamp) for + * a batch of samples. Only the first sample will have the correct + * timestamp. So we must interpolate the other samples. + * We use the previous batch timestamp and our current batch timestamp + * as a way to calculate period, then spread the samples evenly. + * + * s0 int, 0ms + * s1 int, 10ms + * s2 int, 20ms + * 30ms point goes by, no interrupt, previous one is still asserted + * downloading s2 and s3 + * s3 sample, 20ms (incorrect timestamp) + * s4 int, 40ms + * + * The batches are [(s0), (s1), (s2, s3), (s4)]. Since the 3rd batch + * has 2 samples in them, we adjust the timestamp of s3. + * s2 - s1 = 10ms, so s3 must be s2 + 10ms => 20ms. If s1 would have + * been part of a bigger batch things would have gotten a little + * more complicated. + * + * Note: we also assume another sensor sample doesn't break up a batch + * in 2 or more partitions. Example, there can't ever be a sync sensor + * in between S2 and S3. This simplifies the following code. + */ +static void cros_ec_ring_spread_add( + struct cros_ec_sensorhub *sensorhub, + unsigned long sensor_mask, + struct cros_ec_sensors_ring_sample *last_out) +{ + struct cros_ec_sensors_ring_sample *batch_start, *next_batch_start; + int id; + + for_each_set_bit(id, &sensor_mask, BITS_PER_LONG) { + for (batch_start = sensorhub->ring; batch_start < last_out; + batch_start = next_batch_start) { + /* + * For each batch (where all samples have the same + * timestamp). + */ + int batch_len, sample_idx; + struct cros_ec_sensors_ring_sample *batch_end = + batch_start; + struct cros_ec_sensors_ring_sample *s; + s64 batch_timestamp = batch_start->timestamp; + s64 sample_period; + + /* + * Skip over batches that start with the sensor types + * we're not looking at right now. + */ + if (batch_start->sensor_id != id) { + next_batch_start = batch_start + 1; + continue; + } + + /* + * Do not start a batch + * from a flush, as it happens asynchronously to the + * regular flow of events. + */ + if (batch_start->flag & + MOTIONSENSE_SENSOR_FLAG_FLUSH) { + cros_sensorhub_send_sample( + sensorhub, batch_start); + next_batch_start = batch_start + 1; + continue; + } + + if (batch_start->timestamp <= + sensorhub->last_batch_timestamp[id]) { + + batch_timestamp = + sensorhub->last_batch_timestamp[id]; + batch_len = sensorhub->last_batch_len[id]; + + sample_idx = batch_len; + + sensorhub->last_batch_timestamp[id] = + sensorhub->penultimate_batch_timestamp[id]; + sensorhub->last_batch_len[id] = + sensorhub->penultimate_batch_len[id]; + } else { + /* + * Push first sample in the batch to the, + * kifo, it's guaranteed to be correct, the + * rest will follow later on. + */ + sample_idx = batch_len = 1; + cros_sensorhub_send_sample( + sensorhub, batch_start); + batch_start++; + } + + /* Find all samples have the same timestamp. */ + for (s = batch_start; s < last_out; s++) { + if (s->sensor_id != id) + /* + * Skip over other sensor types that + * are interleaved, don't count them. + */ + continue; + if (s->timestamp != batch_timestamp) + /* we discovered the next batch */ + break; + if (s->flag & MOTIONSENSE_SENSOR_FLAG_FLUSH) + /* break on flush packets */ + break; + batch_end = s; + batch_len++; + } + + if (batch_len == 1) + goto done_with_this_batch; + + /* Can we calculate period? */ + if (sensorhub->last_batch_len[id] == 0) { + dev_warn(sensorhub->dev, "Sensor %d: lost %d samples when spreading\n", + id, batch_len - 1); + goto done_with_this_batch; + /* + * Note: we're dropping the rest of the samples + * in this batch since we have no idea where + * they're supposed to go without a period + * calculation. + */ + } + + sample_period = div_s64(batch_timestamp - + sensorhub->last_batch_timestamp[id], + sensorhub->last_batch_len[id]); + dev_dbg(sensorhub->dev, + "Adjusting %d samples, sensor %d last_batch @%lld (%d samples) batch_timestamp=%lld => period=%lld\n", + batch_len, id, + sensorhub->last_batch_timestamp[id], + sensorhub->last_batch_len[id], + batch_timestamp, + sample_period); + + /* + * Adjust timestamps of the samples then push them to + * kfifo. + */ + for (s = batch_start; s <= batch_end; s++) { + if (s->sensor_id != id) + /* + * Skip over other sensor types that + * are interleaved, don't change them. + */ + continue; + + s->timestamp = batch_timestamp + + sample_period * sample_idx; + sample_idx++; + + cros_sensorhub_send_sample(sensorhub, s); + } + +done_with_this_batch: + sensorhub->penultimate_batch_timestamp[id] = + sensorhub->last_batch_timestamp[id]; + sensorhub->penultimate_batch_len[id] = + sensorhub->last_batch_len[id]; + + sensorhub->last_batch_timestamp[id] = batch_timestamp; + sensorhub->last_batch_len[id] = batch_len; + + next_batch_start = batch_end + 1; + } + } +} + +/* + * cros_ec_ring_spread_add_legacy: Calculate proper timestamps then * add to ringbuffer (legacy). * + * Note: This assumes we're running old firmware, where every sample's timestamp + * is after the sample. Run if tight_timestamps == false. + * * If there is a sample with a proper timestamp * timestamp | count * older_unprocess_out --> TS1 | 1 @@ -204,7 +663,7 @@ static bool cros_ec_ring_process_event( * out --> TS1 | 3 * We know have [TS1+1/3, TS1+2/3, current timestamp] */ -static void cros_ec_ring_spread_add( +static void cros_ec_ring_spread_add_legacy( struct cros_ec_sensorhub *sensorhub, unsigned long sensor_mask, s64 current_timestamp, @@ -274,7 +733,7 @@ static void cros_ec_ring_spread_add( cros_sensorhub_send_sample(sensorhub, out); } -/* +/** * cros_ec_sensorhub_ring_handler - the trigger handler function * * @sensorhub: device information. @@ -391,7 +850,8 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub) * the AP is slow to respond to the IRQ, the EC may have added new * samples. Use the FIFO info timestamp as last timestamp then. */ - if ((last_out-1)->timestamp == current_timestamp) + if (!sensorhub->tight_timestamps && + (last_out-1)->timestamp == current_timestamp) current_timestamp = fifo_timestamp; /* Warn on lost samples. */ @@ -403,6 +863,7 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub) dev_warn_ratelimited(sensorhub->dev, "Sensor %d: lost: %d out of %d\n", i, lost, fifo_info->info.total_lost); + sensorhub->last_batch_len[i] = 0; } } } @@ -410,8 +871,11 @@ static void cros_ec_sensorhub_ring_handler(struct cros_ec_sensorhub *sensorhub) /* * Spread samples in case of batching, then add them to the ringbuffer. */ - cros_ec_ring_spread_add(sensorhub, sensor_mask, - current_timestamp, last_out); + if (sensorhub->tight_timestamps) + cros_ec_ring_spread_add(sensorhub, sensor_mask, last_out); + else + cros_ec_ring_spread_add_legacy(sensorhub, sensor_mask, + current_timestamp, last_out); ring_handler_end: sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] = current_timestamp; @@ -479,6 +943,10 @@ int cros_ec_sensorhub_ring_add(struct cros_ec_sensorhub *sensorhub) sensorhub->fifo_timestamp[CROS_EC_SENSOR_LAST_TS] = cros_ec_get_time_ns(); + sensorhub->tight_timestamps = cros_ec_check_features(ec, + EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS); + + /* register the notifier that will act as a top half interrupt. */ sensorhub->notifier.notifier_call = cros_ec_sensorhub_event; ret = blocking_notifier_chain_register(&ec->ec_dev->event_notifier, diff --git a/include/linux/platform_data/cros_ec_sensorhub.h b/include/linux/platform_data/cros_ec_sensorhub.h index 595d010b58d95..aef7b2a1d948d 100644 --- a/include/linux/platform_data/cros_ec_sensorhub.h +++ b/include/linux/platform_data/cros_ec_sensorhub.h @@ -56,6 +56,42 @@ struct cros_ec_sensors_ring_sample { s64 timestamp; } __packed; +/* State used for cros_ec_ring_fix_overflow */ +struct cros_ec_sensors_ec_overflow_state { + s64 offset; + s64 last; +}; + +/* Length of the filter, how long to remember entries for */ +#define CROS_EC_SENSORHUB_TS_HISTORY_SIZE 64 + +/** + * Timestamp filetr state: + * + * @x_offset: x is EC interrupt time. x_offset its last value. + * @y_offset: y is the difference between AP and EC time, y_offset its last + * value. + * @x_history: The past history of x, relative to x_offset. + * @y_history: The past history of y, relative to y_offset. + * @m_history: rate between y and x. + * @temp_buf: Temporary buffer used when updating the filter. + * @mediam_m: median value of m_history + * @mediam_error: final error to apply to AP interrupt timestamp to get the + * "true timestamp" the event occurred. + */ +struct cros_ec_sensors_ts_filter_state { + s64 x_offset, y_offset; + s64 x_history[CROS_EC_SENSORHUB_TS_HISTORY_SIZE]; + s64 y_history[CROS_EC_SENSORHUB_TS_HISTORY_SIZE]; + s64 m_history[CROS_EC_SENSORHUB_TS_HISTORY_SIZE]; + int history_len; + + s64 temp_buf[CROS_EC_SENSORHUB_TS_HISTORY_SIZE]; + + s64 median_m; + s64 median_error; +}; + /* * struct cros_ec_sensorhub - Sensor Hub device data. */ @@ -82,6 +118,35 @@ struct cros_ec_sensorhub { struct cros_ec_fifo_info fifo_info; int fifo_size; + /* Used for timestamp spreading calculations when a batch shows up */ + s64 penultimate_batch_timestamp[CROS_EC_SENSOR_MAX]; + int penultimate_batch_len[CROS_EC_SENSOR_MAX]; + s64 last_batch_timestamp[CROS_EC_SENSOR_MAX]; + int last_batch_len[CROS_EC_SENSOR_MAX]; + s64 newest_sensor_event[CROS_EC_SENSOR_MAX]; + + struct cros_ec_sensors_ec_overflow_state overflow_a; + struct cros_ec_sensors_ec_overflow_state overflow_b; + + struct cros_ec_sensors_ts_filter_state filter; + + /* + * The timestamps reported from the EC have low jitter. + * Timestamps also come before every sample. + * Set either by feature bits coming from the EC or userspace. + */ + bool tight_timestamps; + + /* + * Statistics used to compute shaved time. This occures when + * timestamp interpolation from EC time to AP time accidentally + * puts timestamps in the future. These timestamps are clamped + * to `now` and these count/total_ns maintain the statistics for + * how much time was removed in a given period.. + */ + s32 future_timestamp_count; + s64 future_timestamp_total_ns; + /* * Dynamic array to be able to spread datum to iio sensor objects. */ From patchwork Mon Oct 21 05:53:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201369 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DB794112B for ; Mon, 21 Oct 2019 05:54:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A6FD82089C for ; Mon, 21 Oct 2019 05:54:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="PfgZUBDG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727318AbfJUFyf (ORCPT ); Mon, 21 Oct 2019 01:54:35 -0400 Received: from mail-pg1-f193.google.com ([209.85.215.193]:40474 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727310AbfJUFye (ORCPT ); Mon, 21 Oct 2019 01:54:34 -0400 Received: by mail-pg1-f193.google.com with SMTP id 15so1720454pgt.7 for ; Sun, 20 Oct 2019 22:54:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WJtIyWnycVeHZNXYT1yBsr9fxhf3liFPRNbszaXJ+U8=; b=PfgZUBDGXEdQVUaesV452ZrXTiTj8rPHCiR7ynknCTpxmfOhPNNUT1DnEx+XLEIwkd gj3tQOGPHzVNW5s4Su9svyOfvC2eF0KKOgTZCl6wDMOeB2xQaGInVdrgELyjK0cg1jUA xLI1jZG2iejrKwHEpS7z0/LmlztrsGmkZt1XQ= 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:mime-version:content-transfer-encoding; bh=WJtIyWnycVeHZNXYT1yBsr9fxhf3liFPRNbszaXJ+U8=; b=ixS66jJO8CigtBQP4gmfzbq1FvRx2q/8UwJnpmNtsGQVf3RLDBHXzq5mZbmOOZ0Vwj oFrDp5rhYsX3ZhA8AygbCiCBWEFqF8eGb9GP+we1F5dKMcPIGqgXZfjTZAUxhI8KLW7U ijTqueLZSLCZKod08NkDdd5oA8VnWoE+LLX3t5bR9vtQh54G7URa4ekril7EeTOUMMuB sh9CFVYZ0rRy05I1GlvM9TmBJO/54QAv2ntNSGn+aWJvXd43Ns0qN4FqIBkLa3JyX7HM W0PaSoRpn/bU3xA68VbelSVM24iWQl+08dFNxJA2VTrZmDAp0vsALsM+7xdax4CnM/JQ QE3w== X-Gm-Message-State: APjAAAVfAp07thYZFkW3vEKFGK75dBpOznbHITsv95xOv9NFViA3dwGr gI4R2PISRCwJnUTMiKPtIwqcGQ== X-Google-Smtp-Source: APXvYqzBZpBeN4KR7DhteXwlvFKoFX5C8EvUuCIe122bIvQbeF64cZPGF6CWGOGZTK/joEl0Gh4IzQ== X-Received: by 2002:a17:90a:8c02:: with SMTP id a2mr26573846pjo.79.1571637272765; Sun, 20 Oct 2019 22:54:32 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id u3sm13232365pfn.134.2019.10.20.22.54.31 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:31 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 13/18] iio: cros_ec: Move function description to .c file Date: Sun, 20 Oct 2019 22:53:58 -0700 Message-Id: <20191021055403.67849-14-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org To prevent comment rot, move function description to cros_ec_sensors_core.c. Signed-off-by: Gwendal Grignou Acked-by: Jonathan Cameron --- New in v2. .../cros_ec_sensors/cros_ec_sensors_core.c | 69 ++++++++++++++++ .../linux/iio/common/cros_ec_sensors_core.h | 80 ------------------- 2 files changed, 69 insertions(+), 80 deletions(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 81a7f692de2f3..4acb8b7310d43 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -83,6 +83,14 @@ static void get_default_min_max_freq(enum motionsensor_type type, } } +/** + * cros_ec_sensors_core_init() - basic initialization of the core structure + * @pdev: platform device created for the sensors + * @indio_dev: iio device structure of the device + * @physical_device: true if the device refers to a physical device + * + * Return: 0 on success, -errno on failure. + */ int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device) @@ -160,6 +168,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init); +/** + * cros_ec_motion_send_host_cmd() - send motion sense host command + * @st: pointer to state information for device + * @opt_length: optional length to reduce the response size, useful on the data + * path. Otherwise, the maximal allowed response size is used + * + * When called, the sub-command is assumed to be set in param->cmd. + * + * Return: 0 on success, -errno on failure. + */ int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state, u16 opt_length) { @@ -422,6 +440,14 @@ int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc); +/** + * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol + * @indio_dev: pointer to IIO device + * @scan_mask: bitmap of the sensor indices to scan + * @data: location to store data + * + * Return: 0 on success, -errno on failure. + */ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data) { @@ -446,6 +472,18 @@ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd); +/** + * cros_ec_sensors_capture() - the trigger handler function + * @irq: the interrupt number. + * @p: a pointer to the poll function. + * + * On a trigger event occurring, if the pollfunc is attached then this + * handler is called as a threaded interrupt (and hence may sleep). It + * is responsible for grabbing data from the device and pushing it into + * the associated buffer. + * + * Return: IRQ_HANDLED + */ irqreturn_t cros_ec_sensors_capture(int irq, void *p) { struct iio_poll_func *pf = p; @@ -481,6 +519,16 @@ irqreturn_t cros_ec_sensors_capture(int irq, void *p) } EXPORT_SYMBOL_GPL(cros_ec_sensors_capture); +/** + * cros_ec_sensors_core_read() - function to request a value from the sensor + * @st: pointer to state information for device + * @chan: channel specification structure table + * @val: will contain one element making up the returned value + * @val2: will contain another element making up the returned value + * @mask: specifies which values to be requested + * + * Return: the type of value returned by the device + */ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -521,6 +569,17 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read); +/** + * cros_ec_sensors_core_read_avail() - get available values + * @indio_dev: pointer to state information for device + * @chan: channel specification structure table + * @vals: list of available values + * @type: type of data returned + * @length: number of data returned in the array + * @mask: specifies which values to be requested + * + * Return: an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST + */ int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, const int **vals, @@ -542,6 +601,16 @@ int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail); +/** + * cros_ec_sensors_core_write() - function to write a value to the sensor + * @st: pointer to state information for device + * @chan: channel specification structure table + * @val: first part of value to write + * @val2: second part of value to write + * @mask: specifies which values to write + * + * Return: the type of value returned by the device + */ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask) diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index bb331e6356a9c..0af918978f975 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -79,95 +79,25 @@ struct cros_ec_sensors_core_state { int frequencies[3]; }; -/** - * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory - * @indio_dev: pointer to IIO device - * @scan_mask: bitmap of the sensor indices to scan - * @data: location to store data - * - * This is the safe function for reading the EC data. It guarantees that the - * data sampled was not modified by the EC while being read. - * - * Return: 0 on success, -errno on failure. - */ int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); -/** - * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol - * @indio_dev: pointer to IIO device - * @scan_mask: bitmap of the sensor indices to scan - * @data: location to store data - * - * Return: 0 on success, -errno on failure. - */ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); struct platform_device; -/** - * cros_ec_sensors_core_init() - basic initialization of the core structure - * @pdev: platform device created for the sensors - * @indio_dev: iio device structure of the device - * @physical_device: true if the device refers to a physical device - * - * Return: 0 on success, -errno on failure. - */ int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device); -/** - * cros_ec_sensors_capture() - the trigger handler function - * @irq: the interrupt number. - * @p: a pointer to the poll function. - * - * On a trigger event occurring, if the pollfunc is attached then this - * handler is called as a threaded interrupt (and hence may sleep). It - * is responsible for grabbing data from the device and pushing it into - * the associated buffer. - * - * Return: IRQ_HANDLED - */ irqreturn_t cros_ec_sensors_capture(int irq, void *p); -/** - * cros_ec_motion_send_host_cmd() - send motion sense host command - * @st: pointer to state information for device - * @opt_length: optional length to reduce the response size, useful on the data - * path. Otherwise, the maximal allowed response size is used - * - * When called, the sub-command is assumed to be set in param->cmd. - * - * Return: 0 on success, -errno on failure. - */ int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st, u16 opt_length); -/** - * cros_ec_sensors_core_read() - function to request a value from the sensor - * @st: pointer to state information for device - * @chan: channel specification structure table - * @val: will contain one element making up the returned value - * @val2: will contain another element making up the returned value - * @mask: specifies which values to be requested - * - * Return: the type of value returned by the device - */ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int *val, int *val2, long mask); -/** - * cros_ec_sensors_core_read_avail() - get available values - * @indio_dev: pointer to state information for device - * @chan: channel specification structure table - * @vals: list of available values - * @type: type of data returned - * @length: number of data returned in the array - * @mask: specifies which values to be requested - * - * Return: an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST - */ int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, const int **vals, @@ -175,16 +105,6 @@ int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, int *length, long mask); -/** - * cros_ec_sensors_core_write() - function to write a value to the sensor - * @st: pointer to state information for device - * @chan: channel specification structure table - * @val: first part of value to write - * @val2: second part of value to write - * @mask: specifies which values to write - * - * Return: the type of value returned by the device - */ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask); From patchwork Mon Oct 21 05:53:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201379 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5AECE1575 for ; Mon, 21 Oct 2019 05:54:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 264D72089C for ; Mon, 21 Oct 2019 05:54:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="VS1NUdeE" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727315AbfJUFyf (ORCPT ); Mon, 21 Oct 2019 01:54:35 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:34873 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727307AbfJUFyf (ORCPT ); Mon, 21 Oct 2019 01:54:35 -0400 Received: by mail-pl1-f193.google.com with SMTP id c3so6080163plo.2 for ; Sun, 20 Oct 2019 22:54:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/S7uG+di49uMPvOgcSRYYqyni8kI/2um7+75z2ze7EY=; b=VS1NUdeE1rjAVyLQedmXw05r3lRRUCT5pHH1J7iDxWLMne7iBSdK/zBrGc5//H/twr bVpOkj7/cCsufgvaRwrkdBt/I6RWubQvBWxLhA8+yT9zm3DRSw5FKwCIqfWkpQ6VxECx 12K97LOZO3VuQ5jFdiB8GcsidtZH+LKe+oEiw= 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:mime-version:content-transfer-encoding; bh=/S7uG+di49uMPvOgcSRYYqyni8kI/2um7+75z2ze7EY=; b=DKnasH0z6gVpkPOsyZJzpO/PGvJCpk2tVEuWfW/gl+BUBCo8hss55sjXbE7MfhwKhK 1cDE38l8rHOdjYDfMBLLQj7k9Ft66dwSZffYtcPbFpAhgodhcKODHUxuqWxCXToeK4Ll Q4kGICQNom3twr+2R0iX0h3KF5URCJWdnwxLsdHeHPfmviACeq+KcsH73yp92i7U7Qiy vmv+8QQA34k9fpY/rrzXkvT4qwP/Z/9SR1MCFAqSLHF7v7vaKRQby0lP8qQTMexSRWBB LsParc5QKb72fkANdRcGeqY+Cj4dwomtSIgi/4Cik9BtPxBkGXIwCC8Kg1UZGz/EV6IV PWOQ== X-Gm-Message-State: APjAAAVPnteofJ1b8lqj3m5P3bsS/5ps65CF7orRb1xx5JrUM1cVS1R6 xHy1YHgDODMWvKipv/Niw4gVBw== X-Google-Smtp-Source: APXvYqw5S8nqbkIKX+b4p1M98ZBDewBoSytKdsUdOY4S5XmVdraHSf0rpR9Nn2yoAoPDDS+YS9bnMQ== X-Received: by 2002:a17:902:9308:: with SMTP id bc8mr22485990plb.178.1571637274014; Sun, 20 Oct 2019 22:54:34 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id u7sm14322508pfn.61.2019.10.20.22.54.33 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:33 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 14/18] iio: cros_ec: Register to cros_ec_sensorhub when EC supports FIFO Date: Sun, 20 Oct 2019 22:53:59 -0700 Message-Id: <20191021055403.67849-15-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org When EC supports FIFO, each IIO device registers a callback, to put samples in the buffer when they arrives from the FIFO. We can still use a trigger to collect samples, but there may be some duplications in the buffer: EC has a single FIFO, so once one sensor is using it, all sensors event will be in the FIFO. To be sure events generated by cros_ec_sensorhub or the trigger uses the same time domain, current_timestamp_clock must be set to "boottime". When no FIFO, the user space app needs to call trigger_new, or better register a high precision timer. Signed-off-by: Gwendal Grignou --- Change in v2 from "Use triggered buffer only when EC does not support FIFO": - Keep trigger all the time. - Add devm_add_action to cleanup callback registration. - EC that "reports" legacy sensors do not have FIFO. - Use iiio_is_buffer_enabled instead of checking the scan_mask before sending samples to buffer. - Add empty lines for visibility. drivers/iio/accel/cros_ec_accel_legacy.c | 8 +- .../cros_ec_sensors/cros_ec_lid_angle.c | 2 +- .../common/cros_ec_sensors/cros_ec_sensors.c | 8 +- .../cros_ec_sensors/cros_ec_sensors_core.c | 80 ++++++++++++++++++- drivers/iio/light/cros_ec_light_prox.c | 8 +- drivers/iio/pressure/cros_ec_baro.c | 8 +- .../linux/iio/common/cros_ec_sensors_core.h | 12 ++- 7 files changed, 96 insertions(+), 30 deletions(-) diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index 65f85faf6f31d..66683df9fc433 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -171,7 +171,8 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, + cros_ec_sensors_capture, NULL); if (ret) return ret; @@ -191,11 +192,6 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) state->sign[CROS_EC_SENSOR_Z] = -1; } - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, - cros_ec_sensors_capture, NULL); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c index 1dcc2a16ab2dd..e30a59fcf0f95 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c @@ -97,7 +97,7 @@ static int cros_ec_lid_angle_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - ret = cros_ec_sensors_core_init(pdev, indio_dev, false); + ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, NULL); if (ret) return ret; diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 7dce044734678..9e7903ff99f80 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -231,7 +231,8 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, + cros_ec_sensors_capture, cros_ec_sensors_push_data); if (ret) return ret; @@ -293,11 +294,6 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) else state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, - cros_ec_sensors_capture, NULL); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 4acb8b7310d43..3d2e17093c75a 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -83,17 +84,72 @@ static void get_default_min_max_freq(enum motionsensor_type type, } } +int cros_ec_sensors_push_data( + struct iio_dev *indio_dev, + s16 *data, + s64 timestamp) +{ + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + s16 *out; + unsigned int i; + + /* + * It can happen if we get a samples before the iio device is fully + * registered. + */ + if (!st) + return 0; + + /* + * Ignore samples if the buffer is not set: it is needed if the ODR is + * set but the buffer is not enabled yet. + */ + if (!iio_buffer_enabled(indio_dev)) + return 0; + + out = (s16 *)st->samples; + for_each_set_bit(i, + indio_dev->active_scan_mask, + indio_dev->masklength) { + *out = data[i]; + out++; + } + + iio_push_to_buffers_with_timestamp(indio_dev, st->samples, timestamp); + + return 0; +} +EXPORT_SYMBOL_GPL(cros_ec_sensors_push_data); + +static void cros_ec_sensors_core_clean(void *arg) +{ + struct platform_device *pdev = (struct platform_device *)arg; + struct cros_ec_sensorhub *sensor_hub = + dev_get_drvdata(pdev->dev.parent); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + u8 sensor_num = st->param.info.sensor_num; + + cros_ec_sensorhub_unregister_push_data(sensor_hub, sensor_num); +} + /** * cros_ec_sensors_core_init() - basic initialization of the core structure * @pdev: platform device created for the sensors * @indio_dev: iio device structure of the device * @physical_device: true if the device refers to a physical device + * @trigger_capture: function pointer to call buffer is triggered, + * for backward compatibility. + * @push_data: function to call when cros_ec_sensorhub receives + * a sample for that sensor. * * Return: 0 on success, -errno on failure. */ int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, - bool physical_device) + bool physical_device, + cros_ec_sensors_capture_t trigger_capture, + cros_ec_sensorhub_push_data_cb_t push_data) { struct device *dev = &pdev->dev; struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); @@ -132,8 +188,6 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, indio_dev->name = pdev->name; if (physical_device) { - indio_dev->modes = INDIO_DIRECT_MODE; - state->param.cmd = MOTIONSENSE_CMD_INFO; state->param.info.sensor_num = sensor_platform->sensor_num; ret = cros_ec_motion_send_host_cmd(state, 0); @@ -162,9 +216,27 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, state->frequencies[2] = state->resp->info_3.max_frequency; } + + ret = devm_iio_triggered_buffer_setup( + dev, indio_dev, NULL, + trigger_capture, NULL); + if (ret) + return ret; + + if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) { + ret = cros_ec_sensorhub_register_push_data( + sensor_hub, + sensor_platform->sensor_num, + indio_dev, push_data); + if (ret) + return ret; + + ret = devm_add_action_or_reset( + dev, cros_ec_sensors_core_clean, pdev); + } } - return 0; + return ret; } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init); diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index d85a391e50c59..da40c38370965 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -178,7 +178,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, + cros_ec_sensors_capture, cros_ec_sensors_push_data); if (ret) return ret; @@ -237,11 +238,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, - cros_ec_sensors_capture, NULL); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index 2354302375dee..fb7daeb4b29f9 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -134,7 +134,8 @@ static int cros_ec_baro_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - ret = cros_ec_sensors_core_init(pdev, indio_dev, true); + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, + cros_ec_sensors_capture, cros_ec_sensors_push_data); if (ret) return ret; @@ -180,11 +181,6 @@ static int cros_ec_baro_probe(struct platform_device *pdev) state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, - cros_ec_sensors_capture, NULL); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 0af918978f975..b4eb3790cde11 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -12,6 +12,7 @@ #include #include #include +#include enum { CROS_EC_SENSOR_X, @@ -32,6 +33,9 @@ enum { /* Minimum sampling period to use when device is suspending */ #define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000 /* 1 second */ +typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p); + + /** * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver * @ec: cros EC device structure @@ -87,9 +91,15 @@ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, struct platform_device; int cros_ec_sensors_core_init(struct platform_device *pdev, - struct iio_dev *indio_dev, bool physical_device); + struct iio_dev *indio_dev, bool physical_device, + cros_ec_sensors_capture_t trigger_capture, + cros_ec_sensorhub_push_data_cb_t push_data); irqreturn_t cros_ec_sensors_capture(int irq, void *p); +int cros_ec_sensors_push_data( + struct iio_dev *indio_dev, + s16 *data, + s64 timestamp); int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st, u16 opt_length); From patchwork Mon Oct 21 05:54:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201377 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F1677112B for ; Mon, 21 Oct 2019 05:54:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C5CBE21721 for ; Mon, 21 Oct 2019 05:54:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="VESvtTcv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727339AbfJUFyi (ORCPT ); Mon, 21 Oct 2019 01:54:38 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:33601 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727329AbfJUFyi (ORCPT ); Mon, 21 Oct 2019 01:54:38 -0400 Received: by mail-pl1-f196.google.com with SMTP id d22so6084022pls.0 for ; Sun, 20 Oct 2019 22:54:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0VdDH0oiiJrSkc0zfZlLZPe7HDYCACJthi66MKbNDC8=; b=VESvtTcv2DeGmwubIKZAZZMJFC7evaOHf35UgBrRK8OvMQRAo1EAb5N5RbyD6UhdN0 ccHnOmwKLdm28vxymnPaIYWEKGNZiuVT85evQhKayVtpCcFs4vOjk8zxNzI4GBUDbsOv ldCTrsfkM3uEq5Ewar1DxCH0WjdlkX0nqXpvo= 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:mime-version:content-transfer-encoding; bh=0VdDH0oiiJrSkc0zfZlLZPe7HDYCACJthi66MKbNDC8=; b=bdR/mVlgeZjPzuu5t1tAylRz3I/7wz+tMul7glgYZ3F209luABPwzlOF1YO6zb/dkA 9GzzK5dMhj/X94PGQtYJY6Iw335sOLKpOjyRPc4XUeG55ryt9Ya4QS+FhwXFag9h6dRm qmU3xBzdJiHPxwBD181JQ2yzNTUIxTawAsv6RV0CmITamtEnKtuywST3EgMWCYWkvjz0 Yup84TopzjY8USk1VrVJihJX0zVxqQwJx2fieMBJ7OPyysXrWIAnbfG6o+8G8Emhk0i7 f+jt9YC3I1PrRzc7HAV1dJgoglPimL3bAQETfAH/naDxS23Ez8N4rd7OxcoTETabOujD Weuw== X-Gm-Message-State: APjAAAUVllpAOoUaYbBzKZuA+4zfc84O7OKmGhzCqE+SQ/7QRCo+R+x5 MPeQcyEkxnVAXLT6EtvCi+8V3A== X-Google-Smtp-Source: APXvYqxD6A6wu+IXtcNCvi1hGS7KVWrz3NngNRwVUv6hnug1LqXcpLl2Xr8zexZuGhHz/NvlNIbSwg== X-Received: by 2002:a17:902:ab82:: with SMTP id f2mr23379055plr.39.1571637275558; Sun, 20 Oct 2019 22:54:35 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id c64sm16902207pfc.19.2019.10.20.22.54.34 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:35 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 15/18] iio: cros_ec: Remove pm function Date: Sun, 20 Oct 2019 22:54:00 -0700 Message-Id: <20191021055403.67849-16-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Since cros_ec_sensorhub is shutting down the FIFO when the device suspends, no need to slow down the EC sampling period rate. It was necesseary to do that before command CMD_FIFO_INT_ENABLE was introduced, but now all supported chromebooks have it. Signed-off-by: Gwendal Grignou Acked-by: Jonathan Cameron --- New in v2. .../cros_ec_sensors/cros_ec_lid_angle.c | 1 - .../common/cros_ec_sensors/cros_ec_sensors.c | 1 - .../cros_ec_sensors/cros_ec_sensors_core.c | 47 ------------------- drivers/iio/light/cros_ec_light_prox.c | 1 - .../linux/iio/common/cros_ec_sensors_core.h | 5 -- 5 files changed, 55 deletions(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c index e30a59fcf0f95..af801e203623e 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c @@ -127,7 +127,6 @@ MODULE_DEVICE_TABLE(platform, cros_ec_lid_angle_ids); static struct platform_driver cros_ec_lid_angle_platform_driver = { .driver = { .name = DRV_NAME, - .pm = &cros_ec_sensors_pm_ops, }, .probe = cros_ec_lid_angle_probe, .id_table = cros_ec_lid_angle_ids, diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 9e7903ff99f80..2eb4bb254fbde 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -314,7 +314,6 @@ MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids); static struct platform_driver cros_ec_sensors_platform_driver = { .driver = { .name = "cros-ec-sensors", - .pm = &cros_ec_sensors_pm_ops, }, .probe = cros_ec_sensors_probe, .id_table = cros_ec_sensors_ids, diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 3d2e17093c75a..e89c355bb4b35 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -716,52 +716,5 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write); -static int __maybe_unused cros_ec_sensors_prepare(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); - - if (st->curr_sampl_freq == 0) - return 0; - - /* - * If the sensors are sampled at high frequency, we will not be able to - * sleep. Set sampling to a long period if necessary. - */ - if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) { - mutex_lock(&st->cmd_lock); - st->param.cmd = MOTIONSENSE_CMD_EC_RATE; - st->param.ec_rate.data = CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY; - cros_ec_motion_send_host_cmd(st, 0); - mutex_unlock(&st->cmd_lock); - } - return 0; -} - -static void __maybe_unused cros_ec_sensors_complete(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); - - if (st->curr_sampl_freq == 0) - return; - - if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) { - mutex_lock(&st->cmd_lock); - st->param.cmd = MOTIONSENSE_CMD_EC_RATE; - st->param.ec_rate.data = st->curr_sampl_freq; - cros_ec_motion_send_host_cmd(st, 0); - mutex_unlock(&st->cmd_lock); - } -} - -const struct dev_pm_ops cros_ec_sensors_pm_ops = { -#ifdef CONFIG_PM_SLEEP - .prepare = cros_ec_sensors_prepare, - .complete = cros_ec_sensors_complete -#endif -}; -EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops); - MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index da40c38370965..6bac02cdd898a 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -255,7 +255,6 @@ MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids); static struct platform_driver cros_ec_light_prox_platform_driver = { .driver = { .name = "cros-ec-light-prox", - .pm = &cros_ec_sensors_pm_ops, }, .probe = cros_ec_light_prox_probe, .id_table = cros_ec_light_prox_ids, diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index b4eb3790cde11..db3da7ffcc376 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -30,9 +30,6 @@ enum { */ #define CROS_EC_SAMPLE_SIZE (sizeof(s64) * 2) -/* Minimum sampling period to use when device is suspending */ -#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000 /* 1 second */ - typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p); @@ -119,8 +116,6 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask); -extern const struct dev_pm_ops cros_ec_sensors_pm_ops; - /* List of extended channel specification for all sensors */ extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[]; From patchwork Mon Oct 21 05:54:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201371 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F38641575 for ; Mon, 21 Oct 2019 05:54:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BFA3E21929 for ; Mon, 21 Oct 2019 05:54:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="FyBf75UP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727319AbfJUFyj (ORCPT ); Mon, 21 Oct 2019 01:54:39 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:46013 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727329AbfJUFyj (ORCPT ); Mon, 21 Oct 2019 01:54:39 -0400 Received: by mail-pf1-f196.google.com with SMTP id y72so7678966pfb.12 for ; Sun, 20 Oct 2019 22:54:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aE7g7XjdeY6aUmgaD/ZeDVZpIgEzF6Nh2eVf/ntj2P0=; b=FyBf75UPec4YJENsnoJ52sSw2ts45Sid1X5tNKB7c9F8KTK6b7wO5IR3iAWALH3yYQ j6N7tK2P/4TVMZaiwhcim5NwYL5zuu+WHEVQfSNgO806ivlVxHQQwwutR+7ZREjTvZ8M wRdEMgBQ2dbzETWddN9j5x6MOavS+vukp812k= 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:mime-version:content-transfer-encoding; bh=aE7g7XjdeY6aUmgaD/ZeDVZpIgEzF6Nh2eVf/ntj2P0=; b=fuTBsqog1zMdaxqq5qXfsicnjUMyqutbeV2z4kYH8aU28zm7SziF6gNwt83s3HzMf2 sgm1Lckc04vnyVigDOmVlYJCWC3TTw4E4ljdv8/jIjK3EW5hLMEfOj9oCWCL9aedQ9TX PRrA34iNWI2xe7i5yNOHkl1Yx/UpkAnzO+VC4FtqL1xsi7lDXjPGN96tFmBIPAxEX8ri aCvie6xV7UgDcQ8ffRD4CprN3bNvM5Bq0KF4L2XIEe72T1NkOC2G1Pu4ENrTo7f1mIb6 i8TH91A+2QTTOsgokhTW7t6L5VoHYz6yVH/ifs3TMWtZlOHZWoGqLJZ9k7lwngwoAtFL wWEg== X-Gm-Message-State: APjAAAVv3mC9L7OwSM50uN9aEmlBD5rN28dClwJMRCzbraPhpfPMDnec riPEjQ9+iSrpUZ5m3RNEil1kyw== X-Google-Smtp-Source: APXvYqxa6lqrq7suP2Tps/yth0GYAA7igkwh43zo/+6iHkit6clEm1WP1xZLF3sO1Cx8Vz3s0cnF5g== X-Received: by 2002:a17:90a:e397:: with SMTP id b23mr27115884pjz.51.1571637276872; Sun, 20 Oct 2019 22:54:36 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id q30sm14244649pja.18.2019.10.20.22.54.36 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:36 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 16/18] iio: cros_ec: Expose hwfifo_timeout Date: Sun, 20 Oct 2019 22:54:01 -0700 Message-Id: <20191021055403.67849-17-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Expose EC minimal interrupt period through buffer/hwfifo_timeout: - Maximal timeout is limited to 65s. - When timeout for all sensors is set to 0, EC will not send events, even if the sensor sampling rate is greater than 0. - curr_sample_rate is no more, the pm functions have been removed. Rename frequency to sampling_frequency to match IIO ABI. Signed-off-by: Gwendal Grignou Acked-by: Jonathan Cameron --- Changes in v2: - Register fifo_attributes in sensors drivers that previously advertise that feature. .../common/cros_ec_sensors/cros_ec_sensors.c | 4 +- .../cros_ec_sensors/cros_ec_sensors_core.c | 95 ++++++++++++++----- drivers/iio/light/cros_ec_light_prox.c | 6 +- drivers/iio/pressure/cros_ec_baro.c | 6 +- .../linux/iio/common/cros_ec_sensors_core.h | 4 +- 5 files changed, 85 insertions(+), 30 deletions(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 2eb4bb254fbde..8c57a3ade78ed 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -236,6 +236,9 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) if (ret) return ret; + iio_buffer_set_attrs(indio_dev->buffer, + cros_ec_sensor_fifo_attributes); + indio_dev->info = &ec_sensors_info; state = iio_priv(indio_dev); for (channel = state->channels, i = CROS_EC_SENSOR_X; @@ -247,7 +250,6 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) BIT(IIO_CHAN_INFO_CALIBSCALE); channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_FREQUENCY) | BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ); diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index e89c355bb4b35..92128c67a166e 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,77 @@ static void get_default_min_max_freq(enum motionsensor_type type, } } +static int cros_ec_sensor_set_ec_rate(struct cros_ec_sensors_core_state *st, + int rate) +{ + int ret; + + if (rate > U16_MAX) + rate = U16_MAX; + + mutex_lock(&st->cmd_lock); + st->param.cmd = MOTIONSENSE_CMD_EC_RATE; + st->param.ec_rate.data = rate; + ret = cros_ec_motion_send_host_cmd(st, 0); + mutex_unlock(&st->cmd_lock); + return ret; +} + +static ssize_t cros_ec_sensor_set_report_latency(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int integer, fract, ret; + int latency; + + ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + /* EC rate is in ms. */ + latency = integer * 1000 + fract / 1000; + ret = cros_ec_sensor_set_ec_rate(st, latency); + if (ret < 0) + return ret; + + return len; +} + +static ssize_t cros_ec_sensor_get_report_latency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int latency, ret; + + mutex_lock(&st->cmd_lock); + st->param.cmd = MOTIONSENSE_CMD_EC_RATE; + st->param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE; + + ret = cros_ec_motion_send_host_cmd(st, 0); + latency = st->resp->ec_rate.ret; + mutex_unlock(&st->cmd_lock); + if (ret < 0) + return ret; + + return sprintf(buf, "%d.%06u\n", + latency / 1000, + (latency % 1000) * 1000); +} + +static IIO_DEVICE_ATTR(hwfifo_timeout, 0644, + cros_ec_sensor_get_report_latency, + cros_ec_sensor_set_report_latency, 0); + +const struct attribute *cros_ec_sensor_fifo_attributes[] = { + &iio_dev_attr_hwfifo_timeout.dev_attr.attr, + NULL, +}; +EXPORT_SYMBOL_GPL(cros_ec_sensor_fifo_attributes); + int cros_ec_sensors_push_data( struct iio_dev *indio_dev, s16 *data, @@ -609,18 +681,6 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: - st->param.cmd = MOTIONSENSE_CMD_EC_RATE; - st->param.ec_rate.data = - EC_MOTION_SENSE_NO_VALUE; - - ret = cros_ec_motion_send_host_cmd(st, 0); - if (ret) - break; - - *val = st->resp->ec_rate.ret; - ret = IIO_VAL_INT; - break; - case IIO_CHAN_INFO_FREQUENCY: st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; st->param.sensor_odr.data = EC_MOTION_SENSE_NO_VALUE; @@ -690,7 +750,7 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, int ret; switch (mask) { - case IIO_CHAN_INFO_FREQUENCY: + case IIO_CHAN_INFO_SAMP_FREQ: st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; st->param.sensor_odr.data = val; @@ -699,15 +759,6 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, ret = cros_ec_motion_send_host_cmd(st, 0); break; - case IIO_CHAN_INFO_SAMP_FREQ: - st->param.cmd = MOTIONSENSE_CMD_EC_RATE; - st->param.ec_rate.data = val; - - ret = cros_ec_motion_send_host_cmd(st, 0); - if (ret) - break; - st->curr_sampl_freq = val; - break; default: ret = -EINVAL; break; diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 6bac02cdd898a..059aaddc91fd8 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -183,6 +183,9 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) if (ret) return ret; + iio_buffer_set_attrs(indio_dev->buffer, + cros_ec_sensor_fifo_attributes); + indio_dev->info = &cros_ec_light_prox_info; state = iio_priv(indio_dev); state->core.type = state->core.resp->info.type; @@ -191,8 +194,7 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) /* Common part */ channel->info_mask_shared_by_all = - BIT(IIO_CHAN_INFO_SAMP_FREQ) | - BIT(IIO_CHAN_INFO_FREQUENCY); + BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->scan_type.realbits = CROS_EC_SENSOR_BITS; diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index fb7daeb4b29f9..e933a1bb64d4b 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -139,6 +139,9 @@ static int cros_ec_baro_probe(struct platform_device *pdev) if (ret) return ret; + iio_buffer_set_attrs(indio_dev->buffer, + cros_ec_sensor_fifo_attributes); + indio_dev->info = &cros_ec_baro_info; state = iio_priv(indio_dev); state->core.type = state->core.resp->info.type; @@ -148,8 +151,7 @@ static int cros_ec_baro_probe(struct platform_device *pdev) channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_SAMP_FREQ) | - BIT(IIO_CHAN_INFO_FREQUENCY); + BIT(IIO_CHAN_INFO_SAMP_FREQ); channel->scan_type.realbits = CROS_EC_SENSOR_BITS; channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; channel->scan_type.shift = 0; diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index db3da7ffcc376..387ca9e61dac8 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -51,7 +51,6 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p); * the timestamp. The timestamp is always last and * is always 8-byte aligned. * @read_ec_sensors_data: function used for accessing sensors values - * @cuur_sampl_freq: current sampling period */ struct cros_ec_sensors_core_state { struct cros_ec_device *ec; @@ -74,8 +73,6 @@ struct cros_ec_sensors_core_state { int (*read_ec_sensors_data)(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); - int curr_sampl_freq; - /* Table of known available frequencies : 0, Min and Max in mHz */ int frequencies[3]; }; @@ -118,5 +115,6 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, /* List of extended channel specification for all sensors */ extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[]; +extern const struct attribute *cros_ec_sensor_fifo_attributes[]; #endif /* __CROS_EC_SENSORS_CORE_H */ From patchwork Mon Oct 21 05:54:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201375 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9C207112B for ; Mon, 21 Oct 2019 05:54:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7B49421721 for ; Mon, 21 Oct 2019 05:54:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="bjYbwrM0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727361AbfJUFyk (ORCPT ); Mon, 21 Oct 2019 01:54:40 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:37910 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727356AbfJUFyj (ORCPT ); Mon, 21 Oct 2019 01:54:39 -0400 Received: by mail-pf1-f193.google.com with SMTP id h195so7692945pfe.5 for ; Sun, 20 Oct 2019 22:54:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=y8VvIDEUzgzOMc6xpWZ3lCTYzI69DQPFZmVj3lTRNRw=; b=bjYbwrM0vAFomwWAxnewGnzfPMxYI7qz90WNYhoErZZ2KaPma2q9lAVzN6YR4esmfq 8OhInS6RGIdaSNObOM4//0A3vpF2PMLse2i6Lzt1sQQfW87868lyaZreKtHwGjL0lDdm yEJPWUqk8vUQDWcosvYF0+a6oIMBtCgJ2Cd+0= 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:mime-version:content-transfer-encoding; bh=y8VvIDEUzgzOMc6xpWZ3lCTYzI69DQPFZmVj3lTRNRw=; b=XxgYQCDtc7s5NgjUABrWd4ryV3m0azRXeNbA/Uk+4uvI+MOewG3y5nn1BfP+/JWnZ0 ETl7LhR2Q/aFsSd2fT30hFIU/oEHmyHITcWsz1aKWQ7LKeqJXQhxG94jVdnpO2ZClqMa OJLwTDULVZgZsLuZgj0ul19g+iDeGNkaMrQ7/X/0BN6bYPG9lUXzuts8UQQd9XKkCkDL lIs3KYqXspC3wwojzmOBurgkYkciKLHAyfIcwkO0RO1faBHer6H4cW2iPygmmZkLWrrq AVSCqIWcp0oGot5kqpCXY1DOslDXUkJ4/gotoRiCykttoCca7maRENeJ8Q0lM+rp4eAA Z54g== X-Gm-Message-State: APjAAAWxgVs/v1cOOA2dbyNVSN2giXHeF6BjxOonf5sOcE+C8zau2zgq ESWPE+YeT9vn834YYyoDPzinDA== X-Google-Smtp-Source: APXvYqztHNMff55mPoiBI7Lm86tfSoxkcF39JDu/xF5Aw5WiwPe4IYx6LTEp4kiXfqjjS0BaQEywDg== X-Received: by 2002:a63:6d0:: with SMTP id 199mr23068156pgg.96.1571637278614; Sun, 20 Oct 2019 22:54:38 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id h66sm22633572pjb.0.2019.10.20.22.54.37 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:37 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 17/18] iio: cros_ec: Report hwfifo_watermark_max Date: Sun, 20 Oct 2019 22:54:02 -0700 Message-Id: <20191021055403.67849-18-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Report the maximum amount of sample the EC can hold. This is not tunable, but can be useful for application to find out the maximum amount of time it can sleep when hwfifo_timeout is set to a large number. Signed-off-by: Gwendal Grignou Acked-by: Jonathan Cameron --- Changes in v2: - Remove double lines, add line before return for visibility. .../cros_ec_sensors/cros_ec_sensors_core.c | 34 +++++++++++++++++-- .../linux/iio/common/cros_ec_sensors_core.h | 3 ++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 92128c67a166e..f50e239f9a1e9 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -23,6 +23,12 @@ #include #include +/* + * Hard coded to the first device to support sensor fifo. The EC has a 2048 + * byte fifo and will trigger an interrupt when fifo is 2/3 full. + */ +#define CROS_EC_FIFO_SIZE (2048 * 2 / 3) + static char *cros_ec_loc[] = { [MOTIONSENSE_LOC_BASE] = "base", [MOTIONSENSE_LOC_LID] = "lid", @@ -56,8 +62,15 @@ static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev, static void get_default_min_max_freq(enum motionsensor_type type, u32 *min_freq, - u32 *max_freq) + u32 *max_freq, + u32 *max_fifo_events) { + /* + * We don't know fifo size, set to size previously used by older + * hardware. + */ + *max_fifo_events = CROS_EC_FIFO_SIZE; + switch (type) { case MOTIONSENSE_TYPE_ACCEL: case MOTIONSENSE_TYPE_GYRO: @@ -150,8 +163,22 @@ static IIO_DEVICE_ATTR(hwfifo_timeout, 0644, cros_ec_sensor_get_report_latency, cros_ec_sensor_set_report_latency, 0); +static ssize_t hwfifo_watermark_max_show( + struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", st->fifo_max_event_count); +} + +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); + const struct attribute *cros_ec_sensor_fifo_attributes[] = { &iio_dev_attr_hwfifo_timeout.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, NULL, }; EXPORT_SYMBOL_GPL(cros_ec_sensor_fifo_attributes); @@ -281,12 +308,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, if (state->msg->version < 3) { get_default_min_max_freq(state->resp->info.type, &state->frequencies[1], - &state->frequencies[2]); + &state->frequencies[2], + &state->fifo_max_event_count); } else { state->frequencies[1] = state->resp->info_3.min_frequency; state->frequencies[2] = state->resp->info_3.max_frequency; + state->fifo_max_event_count = + state->resp->info_3.fifo_max_event_count; } ret = devm_iio_triggered_buffer_setup( diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 387ca9e61dac8..4df3abd151fbf 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -51,6 +51,7 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p); * the timestamp. The timestamp is always last and * is always 8-byte aligned. * @read_ec_sensors_data: function used for accessing sensors values + * @fifo_max_event_count: Size of the EC sensor FIFO */ struct cros_ec_sensors_core_state { struct cros_ec_device *ec; @@ -73,6 +74,8 @@ struct cros_ec_sensors_core_state { int (*read_ec_sensors_data)(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); + u32 fifo_max_event_count; + /* Table of known available frequencies : 0, Min and Max in mHz */ int frequencies[3]; }; From patchwork Mon Oct 21 05:54:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gwendal Grignou X-Patchwork-Id: 11201373 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0554B1575 for ; Mon, 21 Oct 2019 05:54:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CE8782089C for ; Mon, 21 Oct 2019 05:54:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="JWw77FZC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727397AbfJUFyq (ORCPT ); Mon, 21 Oct 2019 01:54:46 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:42218 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727341AbfJUFyk (ORCPT ); Mon, 21 Oct 2019 01:54:40 -0400 Received: by mail-pf1-f193.google.com with SMTP id q12so7689530pff.9 for ; Sun, 20 Oct 2019 22:54:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7qM0INxFAaQNiMRb7wUF5tXn3Vp3+wTj0LnbR6ZyE/Y=; b=JWw77FZCCgw9YMLZ962GN2ViHYWlECdUlu/nHHxYn24wfZa/tGvxW4dT1MhU+eq1YK PEDnU8MbXqNlsiw2HqjnuRl6po5hzMkxNDVO1Q2XTWuk0ZM1QlWKgTh/YlsUnE0EtGiO GGKdWR19zADEohM382sAw/snKb2AATugWB9js= 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:mime-version:content-transfer-encoding; bh=7qM0INxFAaQNiMRb7wUF5tXn3Vp3+wTj0LnbR6ZyE/Y=; b=M9QcdYLv7jTUWhmsmTQgLiYji4DJYMPXW3OyUgOm8D+YwzQuvULcZ+YrvxnJVq94Ak vgltgYihWtAd/KsALUqMC8zkVTbpjdfzCgd82IgukhzGgibGSFLXoUL6L1D3/LKgNaLW cQp4LKd+0pDdsneza26vKT1C34GFTrkpl8VjS5VGXf0XiedpvWEIf7k9zXL1QdvsMQwM NQg8+MP7gyWykO0Yx8f7ptOsWDCIbsWXYlXR1YkKGRgdAGPLRt0cy/5IqYU8SXTP+s2S s+DiLg3wmwz7XwY70qQxpOECSNw6m3xj+Zyew6ILjv/Vw3QzHq7366ngypMW7dbNb690 /82A== X-Gm-Message-State: APjAAAXIM0uZfqNQ5VsfNbiHA9md8U7sZYQFMx89ZeczvcrVNNctuBht lxVq1ZSDN4q4Ul12n2K/gQod+w== X-Google-Smtp-Source: APXvYqyG3qpMge7NE3llGhFUegOMLLRrvzpwhlN0fGWuEykOP9u2aFiWJvMLJuUBAfhtz8q/dXLFLA== X-Received: by 2002:a63:2f47:: with SMTP id v68mr19033909pgv.318.1571637279955; Sun, 20 Oct 2019 22:54:39 -0700 (PDT) Received: from localhost ([2620:15c:202:1:3c8f:512b:3522:dfaf]) by smtp.gmail.com with ESMTPSA id r24sm14718031pfh.69.2019.10.20.22.54.39 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 20 Oct 2019 22:54:39 -0700 (PDT) From: Gwendal Grignou To: briannorris@chromium.org, jic23@kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, lee.jones@linaro.org, bleung@chromium.org, enric.balletbo@collabora.com, dianders@chromium.org, groeck@chromium.org, fabien.lahoudere@collabora.com Cc: linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, Gwendal Grignou Subject: [PATCH v2 18/18] iio: cros_ec: Use Hertz as unit for sampling frequency Date: Sun, 20 Oct 2019 22:54:03 -0700 Message-Id: <20191021055403.67849-19-gwendal@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021055403.67849-1-gwendal@chromium.org> References: <20191021055403.67849-1-gwendal@chromium.org> MIME-Version: 1.0 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org To be compliant with other sensors, set and get sensor sampling frequency in Hz, not mHz. Fixes: ae7b02ad2f32 ("iio: common: cros_ec_sensors: Expose cros_ec_sensors frequency range via iio sysfs") Signed-off-by: Gwendal Grignou Acked-by: Jonathan Cameron --- No changes in v2. .../cros_ec_sensors/cros_ec_sensors_core.c | 32 +++++++++++-------- .../linux/iio/common/cros_ec_sensors_core.h | 6 ++-- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index f50e239f9a1e9..76dc8cad1b4b5 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -256,6 +256,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, struct cros_ec_dev *ec = sensor_hub->ec; struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); u32 ver_mask; + int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 }; int ret, i; platform_set_drvdata(pdev, indio_dev); @@ -304,20 +305,22 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE; /* 0 is a correct value used to stop the device */ - state->frequencies[0] = 0; if (state->msg->version < 3) { get_default_min_max_freq(state->resp->info.type, - &state->frequencies[1], - &state->frequencies[2], + &frequencies[1], + &frequencies[2], &state->fifo_max_event_count); } else { - state->frequencies[1] = - state->resp->info_3.min_frequency; - state->frequencies[2] = - state->resp->info_3.max_frequency; + frequencies[1] = state->resp->info_3.min_frequency; + frequencies[2] = state->resp->info_3.max_frequency; state->fifo_max_event_count = state->resp->info_3.fifo_max_event_count; } + for (i = 0; i < ARRAY_SIZE(frequencies); i++) { + state->frequencies[2 * i] = frequencies[i] / 1000; + state->frequencies[2 * i + 1] = + (frequencies[i] % 1000) * 1000; + } ret = devm_iio_triggered_buffer_setup( dev, indio_dev, NULL, @@ -707,7 +710,7 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - int ret; + int ret, frequency; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: @@ -719,8 +722,10 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, if (ret) break; - *val = st->resp->sensor_odr.ret; - ret = IIO_VAL_INT; + frequency = st->resp->sensor_odr.ret; + *val = frequency / 1000; + *val2 = (frequency % 1000) * 1000; + ret = IIO_VAL_INT_PLUS_MICRO; break; default: ret = -EINVAL; @@ -755,7 +760,7 @@ int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SAMP_FREQ: *length = ARRAY_SIZE(state->frequencies); *vals = (const int *)&state->frequencies; - *type = IIO_VAL_INT; + *type = IIO_VAL_INT_PLUS_MICRO; return IIO_AVAIL_LIST; } @@ -777,12 +782,13 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, struct iio_chan_spec const *chan, int val, int val2, long mask) { - int ret; + int ret, frequency; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: + frequency = val * 1000 + val2 / 1000; st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; - st->param.sensor_odr.data = val; + st->param.sensor_odr.data = frequency; /* Always roundup, so caller gets at least what it asks for. */ st->param.sensor_odr.roundup = 1; diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 4df3abd151fbf..256447b136296 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -52,6 +52,8 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p); * is always 8-byte aligned. * @read_ec_sensors_data: function used for accessing sensors values * @fifo_max_event_count: Size of the EC sensor FIFO + * @frequencies: Table of known available frequencies: + * 0, Min and Max in mHz. */ struct cros_ec_sensors_core_state { struct cros_ec_device *ec; @@ -75,9 +77,7 @@ struct cros_ec_sensors_core_state { unsigned long scan_mask, s16 *data); u32 fifo_max_event_count; - - /* Table of known available frequencies : 0, Min and Max in mHz */ - int frequencies[3]; + int frequencies[6]; }; int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,