From patchwork Wed Mar 1 14:45:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 94709 Delivered-To: patch@linaro.org Received: by 10.140.20.113 with SMTP id 104csp1827632qgi; Wed, 1 Mar 2017 06:46:27 -0800 (PST) X-Received: by 10.99.108.74 with SMTP id h71mr8896294pgc.99.1488379586984; Wed, 01 Mar 2017 06:46:26 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r11si4799520plj.106.2017.03.01.06.46.26; Wed, 01 Mar 2017 06:46:26 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752100AbdCAOqW (ORCPT + 25 others); Wed, 1 Mar 2017 09:46:22 -0500 Received: from mail-wm0-f51.google.com ([74.125.82.51]:33788 "EHLO mail-wm0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751585AbdCAOpg (ORCPT ); Wed, 1 Mar 2017 09:45:36 -0500 Received: by mail-wm0-f51.google.com with SMTP id i17so8779350wmf.0 for ; Wed, 01 Mar 2017 06:45:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lUg6TxV+L89P/KgNkBol7vD5HgXmOac5J4YpiFQeeqs=; b=XkSgkB7947FTjxSOZbyBIsMEOGuWFah7y201wc5UNW7vURL1xwvc4NrclWu6r0w+wI 7QIiZI280mWgKG/g3yfWEM/q7g6uE3n6J7xCBcTfGslmund7HQ2IaN8ymEXLz3iPVui8 4L2U55dcbryNXngXXFyqpgFm2vIuwtlacU06k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lUg6TxV+L89P/KgNkBol7vD5HgXmOac5J4YpiFQeeqs=; b=O/ICJXwVTpkN6wmkrJppM5oT+m54gMXus+hRTFLgdTjVX6Ceo5Y8+UrUWZt06dElPt me1lUscXF6x511j7AkyewV5gnbrdUZ2gO3X9LxsgLVaQjlMKJ+u/FI7bh3MkzMtjMPOj 6OOYBpGWZvBxV5w4FwZp0J6A0nH0gzpryvhFMGZA267rGcFTW42fFKTyDiCO2cGdHvjh Yv7FFBBRWk4zlJZJ7ciDwLWDuAbIldBSdKee6ePW0baj7UfV/0Gd0gR0bumRVEQOSXY+ 9XyypeAVJD3x3aCBH2UBvuqXwMU0xyqXmYYQAJKdqSj+hqPr2JGZBuzhURZWH5SCR6wf /c5g== X-Gm-Message-State: AMke39lhSjXbFpoQ4OQXW1f8LwBIM4NfmSGoB4j95+FlMrrN5OX3JHz585a/xwoKZWnf4Gte X-Received: by 10.28.133.203 with SMTP id h194mr3712965wmd.122.1488379516808; Wed, 01 Mar 2017 06:45:16 -0800 (PST) Received: from lmenx321.st.com. ([80.215.231.183]) by smtp.gmail.com with ESMTPSA id y145sm23087705wmc.17.2017.03.01.06.45.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 01 Mar 2017 06:45:16 -0800 (PST) From: Benjamin Gaignard X-Google-Original-From: Benjamin Gaignard To: linux-kernel@vger.kernel.org, jic23@kernel.org, linux-iio@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net Cc: fabrice.gasnier@st.com, linaro-kernel@lists.linaro.org, benjamin.gaignard@linaro.org, Benjamin Gaignard Subject: [PATCH v1 1/2] iio: Generalize counting direction modes Date: Wed, 1 Mar 2017 15:45:05 +0100 Message-Id: <1488379506-23969-2-git-send-email-benjamin.gaignard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1488379506-23969-1-git-send-email-benjamin.gaignard@st.com> References: <1488379506-23969-1-git-send-email-benjamin.gaignard@st.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Move counting direction documentation for 104-quad-8 to sysfs-bus-iio to avoid duplicated for other incoming drivers Signed-off-by: Benjamin Gaignard --- Documentation/ABI/testing/sysfs-bus-iio | 14 ++++++++++++++ Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 | 8 -------- 2 files changed, 14 insertions(+), 8 deletions(-) -- 1.9.1 diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index b8f220f..b63723b 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1597,3 +1597,17 @@ Description: provides an absolute positional reference (e.g. a pulse once per revolution) which may be used to home positional systems as required. + +What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available +KernelVersion: 4.12 +Contact: linux-iio@vger.kernel.org +Description: + A list of possible counting directions which are: + - "up" : counter device is increasing. + - "down": counter device is decreasing. + +What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction +KernelVersion: 4.12 +Contact: linux-iio@vger.kernel.org +Description: + Raw counter device counters direction for channel Y. diff --git a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 index ba67652..322c8da 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 +++ b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 @@ -1,4 +1,3 @@ -What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available What: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available What: /sys/bus/iio/devices/iio:deviceX/in_count_noise_error_available What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available @@ -10,13 +9,6 @@ Description: Discrete set of available values for the respective counter configuration are listed in this file. -What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction -KernelVersion: 4.9 -Contact: linux-iio@vger.kernel.org -Description: - Read-only attribute that indicates whether the counter for - channel Y is counting up or down. - What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_mode KernelVersion: 4.9 Contact: linux-iio@vger.kernel.org From patchwork Wed Mar 1 14:45:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 94708 Delivered-To: patch@linaro.org Received: by 10.140.20.113 with SMTP id 104csp1827576qgi; Wed, 1 Mar 2017 06:46:19 -0800 (PST) X-Received: by 10.98.22.87 with SMTP id 84mr9121883pfw.145.1488379578916; Wed, 01 Mar 2017 06:46:18 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 123si4771532pfg.257.2017.03.01.06.46.18; Wed, 01 Mar 2017 06:46:18 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752060AbdCAOqR (ORCPT + 25 others); Wed, 1 Mar 2017 09:46:17 -0500 Received: from mail-wm0-f53.google.com ([74.125.82.53]:36515 "EHLO mail-wm0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751640AbdCAOpg (ORCPT ); Wed, 1 Mar 2017 09:45:36 -0500 Received: by mail-wm0-f53.google.com with SMTP id n11so1041314wma.1 for ; Wed, 01 Mar 2017 06:45:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=d9dMFYGxRgaqxwRECg8DrIgpslaxCPThRpSGON3rVio=; b=dhVseN+Vj+Dea5LYK7ezX3UEe+knXg/JOGD/RfLvM/j83Tu/eg5ZKK///Ojlhsfp8M HtS6QaVMffy4Sq6FCi03xOQgfoaY+oSIcpOPhVxgU2ZzK15okzCr3rR5KjNnS3K/nUSC /DlrjDBlqB85INbgSO9WK/GZdgMIBGKSgnB1A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=d9dMFYGxRgaqxwRECg8DrIgpslaxCPThRpSGON3rVio=; b=WZ3y7HSweodlcCpnYsmfc/ED6q6z7bmLs07gUvXgxXmNrOOY1DE++/N7R3PfTXtFCc cKeRqT6HdLqw0mYO5WUITUZ/6PyPM7Pc8IbHui4lqTItLK5IEJjE1K7XPrfXvIA8Ekck s8Ocd7yycgsQCyGnnjQOsLii8k3V3xo+4q6fcrXlfqVUjNoc3QAfaIDciiExyLAQeBF3 unedDfdELwxc8LhPPHY0yrLQHQta18enV0nC2nMIAJSi4WFX5AGlljqmfR22dNVBCcLq v81b98Q42TSBr4pX6GOQTk1QVumP5v1MkdYwDWGyu91tD4RiMkkn2vf5/ghpLahfMq4W GQRQ== X-Gm-Message-State: AMke39luyz9rUAYv+VPn2IEyT93gay0NkFofAlTxIzN2NPrY4nfXeK+BrBQgJIDMMqGYaQRj X-Received: by 10.28.71.21 with SMTP id u21mr3622845wma.1.1488379518570; Wed, 01 Mar 2017 06:45:18 -0800 (PST) Received: from lmenx321.st.com. ([80.215.231.183]) by smtp.gmail.com with ESMTPSA id y145sm23087705wmc.17.2017.03.01.06.45.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 01 Mar 2017 06:45:17 -0800 (PST) From: Benjamin Gaignard X-Google-Original-From: Benjamin Gaignard To: linux-kernel@vger.kernel.org, jic23@kernel.org, linux-iio@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net Cc: fabrice.gasnier@st.com, linaro-kernel@lists.linaro.org, benjamin.gaignard@linaro.org, Benjamin Gaignard Subject: [PATCH v1 2/2] iio: stm32 trigger: Add counter device Date: Wed, 1 Mar 2017 15:45:06 +0100 Message-Id: <1488379506-23969-3-git-send-email-benjamin.gaignard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1488379506-23969-1-git-send-email-benjamin.gaignard@st.com> References: <1488379506-23969-1-git-send-email-benjamin.gaignard@st.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org One of the features of STM32 trigger hardware block is a counter that can counts up/down depending of the levels and edges of the selected external pins. This patch allow to read/write the counter, get the direction and set the preset value. When counting up preset value is the limit of the counter. When counting down the counter start from preset value down to 0. The hardware have multiple way to use inputs edges and levels to performing counting, those different modes are exposed in: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available and documented in Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 Signed-off-by: Benjamin Gaignard --- .../ABI/testing/sysfs-bus-iio-timer-stm32 | 40 ++++ drivers/iio/trigger/stm32-timer-trigger.c | 231 ++++++++++++++++++++- include/linux/mfd/stm32-timers.h | 2 + 3 files changed, 267 insertions(+), 6 deletions(-) -- 1.9.1 diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 index 6534a60..17933ef 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 @@ -27,3 +27,43 @@ Description: Reading returns the current sampling frequency. Writing an value different of 0 set and start sampling. Writing 0 stop sampling. + +What: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available +KernelVersion: 4.12 +Contact: benjamin.gaignard@st.com +Description: + Reading returns the list of possible counting modes which are: + - "internal_clock": Counter is clocked by the internal clock rising edges. + - "encoder_1" : Counter is clocked by the rising edges of external pin 2 and the counter + direction depend of the level of external pin 1. + - "encoder_2" : Counter is clocked by the rising edges of external pin 1 and the counter + direction depend of the level of external pin 2. + - "encoder_3" : Counter counts up/down on channels 1 & 2 edge depending on channel 1 & 2 level. + Counter is clocked by the rising edges of external pins 1 & 2, + the counter direction is depend of the levels of external pin 1 & 2. + - "reset" : Rising edges on pin 1 reinitializes the counter value to preset value. + - "gated" : Counter counts when external pin level is high. + Counter stops (but is not reset) as soon as external pin becomes low. + - "trigger" : Counter starts at a rising edge of the external pin (but it is not reset). + + Encoder modes are used to automatically handle the counting direction of the internal counter. + Those modes are typically used for high-accuracy rotor position sensing in electrical motors + or for digital potentiometers. From the two outputs of a quadrature encoder sensor the timer + extracts a clock on each and every active edge and adjusts the counting direction depending on + the relative phase-shift between the two incomings signals. The timer counter thus directly + holds the angular position of the motor. + +What: /sys/bus/iio/devices/iio:deviceX/in_count0_count_mode +KernelVersion: 4.12 +Contact: benjamin.gaignard@st.com +Description: + Reading returns the current counting mode. + +What: /sys/bus/iio/devices/iio:deviceX/in_count0_preset +KernelVersion: 4.12 +Contact: benjamin.gaignard@st.com +Description: + Reading returns the current preset value. + Writing set the preset value. + When counting up the counter start from 0 and fire an event when reach preset value. + When counting down the counter start from preset value and fire event when reach 0. diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 994b96d..9026265 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -15,6 +15,7 @@ #include #define MAX_TRIGGERS 6 +#define MAX_VALIDS 5 /* List the triggers created by each timer */ static const void *triggers_table[][MAX_TRIGGERS] = { @@ -32,12 +33,29 @@ { TIM12_TRGO, TIM12_CH1, TIM12_CH2,}, }; +/* List the triggers accepted by each timer */ +static const void *valids_table[][MAX_VALIDS] = { + { TIM5_TRGO, TIM2_TRGO, TIM3_TRGO, TIM4_TRGO,}, + { TIM1_TRGO, TIM8_TRGO, TIM3_TRGO, TIM4_TRGO,}, + { TIM1_TRGO, TIM2_TRGO, TIM5_TRGO, TIM4_TRGO,}, + { TIM1_TRGO, TIM2_TRGO, TIM3_TRGO, TIM8_TRGO,}, + { TIM2_TRGO, TIM3_TRGO, TIM4_TRGO, TIM8_TRGO,}, + { }, /* timer 6 */ + { }, /* timer 7 */ + { TIM1_TRGO, TIM2_TRGO, TIM4_TRGO, TIM5_TRGO,}, + { TIM2_TRGO, TIM3_TRGO,}, + { }, /* timer 10 */ + { }, /* timer 11 */ + { TIM4_TRGO, TIM5_TRGO,}, +}; + struct stm32_timer_trigger { struct device *dev; struct regmap *regmap; struct clk *clk; u32 max_arr; const void *triggers; + const void *valids; }; static int stm32_timer_start(struct stm32_timer_trigger *priv, @@ -180,8 +198,7 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct stm32_timer_trigger *priv = iio_priv(indio_dev); + struct stm32_timer_trigger *priv = dev_get_drvdata(dev); u32 cr2; regmap_read(priv->regmap, TIM_CR2, &cr2); @@ -194,8 +211,7 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct stm32_timer_trigger *priv = iio_priv(indio_dev); + struct stm32_timer_trigger *priv = dev_get_drvdata(dev); int i; for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) { @@ -275,6 +291,203 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) return 0; } +static int stm32_trigger_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + { + u32 cnt; + + regmap_read(priv->regmap, TIM_CNT, &cnt); + *val = cnt; + + return IIO_VAL_INT; + } + } + + return -EINVAL; +} + +static int stm32_trigger_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + { + regmap_write(priv->regmap, TIM_CNT, val); + + return IIO_VAL_INT; + } + } + + return -EINVAL; +} + +static const struct iio_info stm32_trigger_info = { + .driver_module = THIS_MODULE, + .read_raw = stm32_trigger_read_raw, + .write_raw = stm32_trigger_write_raw +}; + +static const char *const stm32_count_modes[] = { + "internal_clock", + "encoder_1", + "encoder_2", + "encoder_3", + "reset", + "gated", + "trigger", +}; + +static int stm32_set_count_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int mode) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + + regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, mode); + + return 0; +} + +static int stm32_get_count_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + u32 smcr; + + regmap_read(priv->regmap, TIM_SMCR, &smcr); + smcr &= TIM_SMCR_SMS; + + return smcr; +} + +static const struct iio_enum stm32_count_mode_enum = { + .items = stm32_count_modes, + .num_items = ARRAY_SIZE(stm32_count_modes), + .set = stm32_set_count_mode, + .get = stm32_get_count_mode +}; + +static const char *const stm32_count_direction_states[] = { + "up", + "down" +}; + +static int stm32_set_count_direction(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int mode) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_DIR, mode); + + return 0; +} + +static int stm32_get_count_direction(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + u32 cr1; + + regmap_read(priv->regmap, TIM_CR1, &cr1); + + return (cr1 & TIM_CR1_DIR); +} + +static const struct iio_enum stm32_count_direction_enum = { + .items = stm32_count_direction_states, + .num_items = ARRAY_SIZE(stm32_count_direction_states), + .set = stm32_set_count_direction, + .get = stm32_get_count_direction +}; + +static ssize_t stm32_count_get_preset(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + u32 arr; + + regmap_read(priv->regmap, TIM_ARR, &arr); + + return snprintf(buf, PAGE_SIZE, "%u\n", arr); +} + +static ssize_t stm32_count_set_preset(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct stm32_timer_trigger *priv = iio_priv(indio_dev); + unsigned int preset; + int ret; + + ret = kstrtouint(buf, 0, &preset); + if (ret) + return ret; + + regmap_write(priv->regmap, TIM_ARR, preset); + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); + + return len; +} + +static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { + { + .name = "preset", + .shared = IIO_SEPARATE, + .read = stm32_count_get_preset, + .write = stm32_count_set_preset + }, + IIO_ENUM("count_direction", IIO_SEPARATE, &stm32_count_direction_enum), + IIO_ENUM_AVAILABLE("count_direction", &stm32_count_direction_enum), + IIO_ENUM("count_mode", IIO_SEPARATE, &stm32_count_mode_enum), + IIO_ENUM_AVAILABLE("count_mode", &stm32_count_mode_enum), + {} +}; + +static const struct iio_chan_spec stm32_trigger_channel = { + .type = IIO_COUNT, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .ext_info = stm32_trigger_count_info, + .indexed = 1 +}; + +static struct stm32_timer_trigger *stm32_setup_iio_device(struct device *dev) +{ + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(dev, + sizeof(struct stm32_timer_trigger)); + if (!indio_dev) + return NULL; + + indio_dev->name = dev_name(dev); + indio_dev->dev.parent = dev; + indio_dev->info = &stm32_trigger_info; + indio_dev->num_channels = 1; + indio_dev->channels = &stm32_trigger_channel; + indio_dev->dev.of_node = dev->of_node; + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return NULL; + + return iio_priv(indio_dev); +} + /** * is_stm32_timer_trigger * @trig: trigger to be checked @@ -299,10 +512,15 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) if (of_property_read_u32(dev->of_node, "reg", &index)) return -EINVAL; - if (index >= ARRAY_SIZE(triggers_table)) + if (index >= ARRAY_SIZE(triggers_table) || + index >= ARRAY_SIZE(valids_table)) return -EINVAL; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + /* Create an IIO device only if we have triggers to be validated */ + if (*valids_table[index]) + priv = stm32_setup_iio_device(dev); + else + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -312,6 +530,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) priv->clk = ddata->clk; priv->max_arr = ddata->max_arr; priv->triggers = triggers_table[index]; + priv->valids = valids_table[index]; ret = stm32_setup_iio_triggers(priv); if (ret) diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h index d030004..4a0abbc 100644 --- a/include/linux/mfd/stm32-timers.h +++ b/include/linux/mfd/stm32-timers.h @@ -21,6 +21,7 @@ #define TIM_CCMR1 0x18 /* Capt/Comp 1 Mode Reg */ #define TIM_CCMR2 0x1C /* Capt/Comp 2 Mode Reg */ #define TIM_CCER 0x20 /* Capt/Comp Enable Reg */ +#define TIM_CNT 0x24 /* Counter */ #define TIM_PSC 0x28 /* Prescaler */ #define TIM_ARR 0x2c /* Auto-Reload Register */ #define TIM_CCR1 0x34 /* Capt/Comp Register 1 */ @@ -30,6 +31,7 @@ #define TIM_BDTR 0x44 /* Break and Dead-Time Reg */ #define TIM_CR1_CEN BIT(0) /* Counter Enable */ +#define TIM_CR1_DIR BIT(4) /* Counter Direction */ #define TIM_CR1_ARPE BIT(7) /* Auto-reload Preload Ena */ #define TIM_CR2_MMS (BIT(4) | BIT(5) | BIT(6)) /* Master mode selection */ #define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */