From patchwork Wed Sep 8 15:54:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier MOYSAN X-Patchwork-Id: 12481447 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 56AF8C4332F for ; Wed, 8 Sep 2021 15:55:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 284E861168 for ; Wed, 8 Sep 2021 15:55:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352187AbhIHP4l (ORCPT ); Wed, 8 Sep 2021 11:56:41 -0400 Received: from mx07-00178001.pphosted.com ([185.132.182.106]:49648 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349730AbhIHP4j (ORCPT ); Wed, 8 Sep 2021 11:56:39 -0400 Received: from pps.filterd (m0241204.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.0.43) with SMTP id 188Fp9gH017908; Wed, 8 Sep 2021 17:55:01 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=selector1; bh=TZ7ZzgGmiyQVX+gn52qM4CzzK4P/AcAj1jnWvuu2uv8=; b=kDVoA0kDr+rZmQIWXpRdOp+k1SQg29BnpogS5Tjg8OGz0Rv2F5LfDK9OR8UrRkZSOjaH 3ASovSR8e2pRv/tsjsq/6c4cQR4XxzKCkbfsGiEjTcWsbQI8ZT0ZXuGo4rw/WUYI4m3g fqqYB5dAZ3cLvsaNwvW9AVsO5+/Zf4p+VxSLAFKDfkJkXcBcA9UKv3453MA3zSL9m2RW KfVc/OPC1BHgT7qOuKmFdQdN9PsrGljI4A7q3edWiW8i9xrzJ8S6NYvz+IEaR6yoMFL4 V5mANyLPFXSnPqA0q/qoCN9BaqCZ1Otyk/QGBswkIxNSlZUCdA1CXxC7YINI0361yk0E 6w== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3axwtygupm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 Sep 2021 17:55:01 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id D5922100034; Wed, 8 Sep 2021 17:54:59 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag1node3.st.com [10.75.127.3]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id BFFEC21E697; Wed, 8 Sep 2021 17:54:59 +0200 (CEST) Received: from localhost (10.75.127.50) by SFHDAG1NODE3.st.com (10.75.127.3) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 8 Sep 2021 17:54:59 +0200 From: Olivier Moysan To: Alexandre Torgue , Arnaud Pouliquen , Fabrice Gasnier , Jonathan Cameron , Lars-Peter Clausen , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , , Subject: [PATCH 1/7] dt-bindings: iio: adc: add generic channel binding Date: Wed, 8 Sep 2021 17:54:46 +0200 Message-ID: <20210908155452.25458-2-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210908155452.25458-1-olivier.moysan@foss.st.com> References: <20210908155452.25458-1-olivier.moysan@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.50] X-ClientProxiedBy: SFHDAG2NODE1.st.com (10.75.127.4) To SFHDAG1NODE3.st.com (10.75.127.3) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-08_06,2021-09-07_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add ADC generic channel binding. This binding should be used as an alternate to legacy channel properties whenever possible. ADC generic channel binding allows to identify supported internal channels through the following reserved label names: "vddcore", "vrefint" and "vbat". This binding also allows to set a different sampling time for each channel. Signed-off-by: Olivier Moysan --- Note: The schema here is too permissive as either legacy or generic channels properties are required. These properties are mutually exclusive, however all attempts to describe this constraint are failing. In particular the following schemas and their variants have shown unsucessful. oneOf: - anyOf: - required: - st,adc-channels - required: - st,adc-diff-channels - anyOf: - required: - $nodename - if: patternProperties: "^channel@([0-9]|1[0-9])$": type: object then: properties: st,adc-channels: false st,adc-diff-channels: false else: - anyOf: - required: - st,adc-channels - required: - st,adc-diff-channels --- .../bindings/iio/adc/st,stm32-adc.yaml | 100 ++++++++++++++++-- 1 file changed, 93 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml index a58334c3bb76..a1f6cbe144ba 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml @@ -222,6 +222,12 @@ patternProperties: '#io-channel-cells': const: 1 + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + interrupts: description: | IRQ Line for the ADC instance. Valid values are: @@ -265,7 +271,9 @@ patternProperties: , ,... vinp and vinn are numbered from 0 to 19. Note: At least one of "st,adc-channels" or "st,adc-diff-channels" is - required. Both properties can be used together. Some channels can be + required if no adc generic channel is defined. These legacy channel + properties are exclusive with adc generic channel bindings. + Both properties can be used together. Some channels can be used as single-ended and some other ones as differential (mixed). But channels can't be configured both as single-ended and differential. $ref: /schemas/types.yaml#/definitions/uint32-matrix @@ -290,6 +298,44 @@ patternProperties: each channel. $ref: /schemas/types.yaml#/definitions/uint32-array + patternProperties: + "^channel@([0-9]|1[0-9])$": + type: object + $ref: "adc.yaml" + description: | + Represents the external channels which are connected to the ADC. + + properties: + reg: + items: + minimum: 0 + maximum: 19 + + label: + description: | + Unique name to identify which channel this is. + Reserved label names "vddcore", "vrefint" and "vbat" + are used to identify internal channels with matching names. + + diff-channels: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + minimum: 0 + maximum: 19 + + st,min-sample-time-nsecs: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Minimum sampling time in nanoseconds. Depending on hardware (board) + e.g. high/low analog input source impedance, fine tune of ADC + sampling time may be recommended. + + required: + - reg + + dependencies: + $nodename: [ '#address-cells', '#size-cells' ] + allOf: - if: properties: @@ -369,12 +415,6 @@ patternProperties: additionalProperties: false - anyOf: - - required: - - st,adc-channels - - required: - - st,adc-diff-channels - required: - compatible - reg @@ -451,4 +491,50 @@ examples: // other adc child node follow... }; + - | + // Example 3: with stm32mp157c to setup ADC2 with: + // - internal channels 13, 14, 15. + #include + #include + adc122: adc@48003000 { + compatible = "st,stm32mp1-adc-core"; + reg = <0x48003000 0x400>; + interrupts = , + ; + clocks = <&rcc ADC12>, <&rcc ADC12_K>; + clock-names = "bus", "adc"; + booster-supply = <&booster>; + vdd-supply = <&vdd>; + vdda-supply = <&vdda>; + vref-supply = <&vref>; + st,syscfg = <&syscfg>; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + adc@100 { + compatible = "st,stm32mp1-adc"; + #io-channel-cells = <1>; + reg = <0x100>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + channel@13 { + reg = <13>; + label = "vrefint"; + st,min-sample-time-nsecs = <9000>; + }; + channel@14 { + reg = <14>; + label = "vddcore"; + st,min-sample-time-nsecs = <9000>; + }; + channel@15 { + reg = <15>; + label = "vbat"; + st,min-sample-time-nsecs = <9000>; + }; + }; + }; + ... From patchwork Wed Sep 8 15:54:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier MOYSAN X-Patchwork-Id: 12481441 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DDCA2C433EF for ; Wed, 8 Sep 2021 15:55:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C3ED86113D for ; Wed, 8 Sep 2021 15:55:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349791AbhIHP4i (ORCPT ); Wed, 8 Sep 2021 11:56:38 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:55194 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S235546AbhIHP4i (ORCPT ); Wed, 8 Sep 2021 11:56:38 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.0.43) with SMTP id 188FpFAY005711; Wed, 8 Sep 2021 17:55:01 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=selector1; bh=khSh/mrGpnueT0O2KuJdaYSLaAOHomTDvZqTp5udFB8=; b=R74YluQh8R8dAh95tRQmIrBjVScGow9vT4Fl4rYs2osr7ODSa4LdIv9k1RSKsOvR5mgt /GeiWP7gYlMuvxiFU0cZyCz4WrGbAD00LR+r2RD35Q32HAiEH4/J+G7W+h1K7YwT2CkH W2lTuq1JgXI++IJAKHr6/L2y04g2MXPkoymdKh4fiux6Hz0+Pe0R5fEcnMXvAaVYKJJJ T6ZfPvlpMjHsXjL97Md6VQ7rGqw5/Qou6QdGSbk4dQqVKLyNOm9XT4uVq1Ha4OrXbzAo W+QnPQyvupY4pvIWXBQCyj69NgQXLrVRQS/AG7lIk6d2RvLy6kfUern4FVPBq52mdXpq xg== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3axtha2b7w-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 Sep 2021 17:55:01 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 9DF02100038; Wed, 8 Sep 2021 17:55:00 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag1node3.st.com [10.75.127.3]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 8CEAB21E697; Wed, 8 Sep 2021 17:55:00 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG1NODE3.st.com (10.75.127.3) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 8 Sep 2021 17:55:00 +0200 From: Olivier Moysan To: Alexandre Torgue , Arnaud Pouliquen , Fabrice Gasnier , Jonathan Cameron , Lars-Peter Clausen , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , , Subject: [PATCH 2/7] dt-bindings: iio: adc: add nvmem support for vrefint internal channel Date: Wed, 8 Sep 2021 17:54:47 +0200 Message-ID: <20210908155452.25458-3-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210908155452.25458-1-olivier.moysan@foss.st.com> References: <20210908155452.25458-1-olivier.moysan@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG1NODE2.st.com (10.75.127.2) To SFHDAG1NODE3.st.com (10.75.127.3) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-08_06,2021-09-07_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add support of nvmem. This allows to retrieve calibration data from OTP for vrefint internal channel. Signed-off-by: Olivier Moysan Acked-by: Rob Herring --- .../devicetree/bindings/iio/adc/st,stm32-adc.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml index a1f6cbe144ba..772e6cf95dc0 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml @@ -298,6 +298,14 @@ patternProperties: each channel. $ref: /schemas/types.yaml#/definitions/uint32-array + nvmem-cells: + items: + - description: Phandle to the calibration vrefint data provided by otp + + nvmem-cell-names: + items: + - const: vrefint + patternProperties: "^channel@([0-9]|1[0-9])$": type: object From patchwork Wed Sep 8 15:54:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier MOYSAN X-Patchwork-Id: 12481443 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36E45C43219 for ; Wed, 8 Sep 2021 15:55:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 22F7A6113D for ; Wed, 8 Sep 2021 15:55:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349884AbhIHP4k (ORCPT ); Wed, 8 Sep 2021 11:56:40 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:33548 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1349720AbhIHP4j (ORCPT ); Wed, 8 Sep 2021 11:56:39 -0400 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.0.43) with SMTP id 188FpSjo007771; Wed, 8 Sep 2021 17:55:02 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=selector1; bh=7c/a7QYZhvYe13U6jCTLYsPuBAp1wOiYKgfl2jIFVcY=; b=2L4kQ7mYj7MML1t1SqDoRR7xgy4GFD2udLFnL1D0YnxoaMpHk0TrD27oPImi4aw9f+0z VbnoyhaFQcM4nuRYtVTZFugUpiVZV0+uk2UJniqH9LwJdGnE4P5UIu/MMQxL0DCk81ci BwicaVykyS7WRCNYaPxJN6cWfdNhqC9y/hh6SrJCUjoZ7zAaAYzazjtOFxSLwyuvKnbN sgWoDaTreEWCK4pZm5EcXa90iRq4WpZHf3FIlNLHN+q7BjIrh/dgDjuwwWhzBgpglSHl oMmhkhQ28QlpGRqssa71CXyIZp/9wizJcOr0EQzCrLQPVbyK9CByuedhuYFxyfZsVfpp Yw== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3axt4majgw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 Sep 2021 17:55:02 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 8B06010002A; Wed, 8 Sep 2021 17:55:01 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag1node3.st.com [10.75.127.3]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 7869D2203A5; Wed, 8 Sep 2021 17:55:01 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG1NODE3.st.com (10.75.127.3) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 8 Sep 2021 17:55:00 +0200 From: Olivier Moysan To: Alexandre Torgue , Arnaud Pouliquen , Fabrice Gasnier , Jonathan Cameron , Lars-Peter Clausen , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , , Subject: [PATCH 3/7] iio: adc stm32-adc: split channel init into several routines Date: Wed, 8 Sep 2021 17:54:48 +0200 Message-ID: <20210908155452.25458-4-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210908155452.25458-1-olivier.moysan@foss.st.com> References: <20210908155452.25458-1-olivier.moysan@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG2NODE3.st.com (10.75.127.6) To SFHDAG1NODE3.st.com (10.75.127.3) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-08_06,2021-09-07_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Split stm32_adc_chan_of_init channel initialization function into several routines to increase readability and prepare channel generic binding handling. Signed-off-by: Olivier Moysan --- drivers/iio/adc/stm32-adc.c | 131 ++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 44 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 5088de835bb1..2f137d14f141 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -194,6 +194,7 @@ struct stm32_adc_cfg { * @smpr_val: sampling time settings (e.g. smpr1 / smpr2) * @cal: optional calibration data on some devices * @chan_name: channel name array + * @num_diff: number of differential channels */ struct stm32_adc { struct stm32_adc_common *common; @@ -217,6 +218,7 @@ struct stm32_adc { u32 smpr_val[2]; struct stm32_adc_calib cal; char chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ]; + u32 num_diff; }; struct stm32_adc_diff_channel { @@ -1706,17 +1708,11 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, } } -static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) +static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm32_adc *adc) { struct device_node *node = indio_dev->dev.of_node; - struct stm32_adc *adc = iio_priv(indio_dev); const struct stm32_adc_info *adc_info = adc->cfg->adc_info; - struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX]; - struct property *prop; - const __be32 *cur; - struct iio_chan_spec *channels; - int scan_index = 0, num_channels = 0, num_diff = 0, ret, i; - u32 val, smp = 0; + int num_channels = 0, ret; ret = of_property_count_u32_elems(node, "st,adc-channels"); if (ret > adc_info->max_channels) { @@ -1727,41 +1723,54 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) } ret = of_property_count_elems_of_size(node, "st,adc-diff-channels", - sizeof(*diff)); + sizeof(struct stm32_adc_diff_channel)); if (ret > adc_info->max_channels) { dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n"); return -EINVAL; } else if (ret > 0) { - int size = ret * sizeof(*diff) / sizeof(u32); - - num_diff = ret; + adc->num_diff = ret; num_channels += ret; + } + + return num_channels; +} + +static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev, + struct stm32_adc *adc, + struct iio_chan_spec *channels) +{ + struct device_node *node = indio_dev->dev.of_node; + const struct stm32_adc_info *adc_info = adc->cfg->adc_info; + struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX]; + u32 num_diff = adc->num_diff; + int size = num_diff * sizeof(*diff) / sizeof(u32); + int scan_index = 0, val, ret, i; + struct property *prop; + const __be32 *cur; + + if (num_diff) { ret = of_property_read_u32_array(node, "st,adc-diff-channels", (u32 *)diff, size); - if (ret) + if (ret) { + dev_err(&indio_dev->dev, "Failed to get diff channels %d\n", ret); return ret; - } + } - if (!num_channels) { - dev_err(&indio_dev->dev, "No channels configured\n"); - return -ENODATA; - } + for (i = 0; i < num_diff; i++) { + if (diff[i].vinp >= adc_info->max_channels || + diff[i].vinn >= adc_info->max_channels) { + dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n", + diff[i].vinp, diff[i].vinn); + return -EINVAL; + } - /* Optional sample time is provided either for each, or all channels */ - ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs"); - if (ret > 1 && ret != num_channels) { - dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n"); - return -EINVAL; + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], + diff[i].vinp, diff[i].vinn, + scan_index, true); + scan_index++; + } } - if (timestamping) - num_channels++; - - channels = devm_kcalloc(&indio_dev->dev, num_channels, - sizeof(struct iio_chan_spec), GFP_KERNEL); - if (!channels) - return -ENOMEM; - of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) { if (val >= adc_info->max_channels) { dev_err(&indio_dev->dev, "Invalid channel %d\n", val); @@ -1771,8 +1780,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) /* Channel can't be configured both as single-ended & diff */ for (i = 0; i < num_diff; i++) { if (val == diff[i].vinp) { - dev_err(&indio_dev->dev, - "channel %d miss-configured\n", val); + dev_err(&indio_dev->dev, "channel %d misconfigured\n", val); return -EINVAL; } } @@ -1781,19 +1789,54 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) scan_index++; } - for (i = 0; i < num_diff; i++) { - if (diff[i].vinp >= adc_info->max_channels || - diff[i].vinn >= adc_info->max_channels) { - dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n", - diff[i].vinp, diff[i].vinn); - return -EINVAL; - } - stm32_adc_chan_init_one(indio_dev, &channels[scan_index], - diff[i].vinp, diff[i].vinn, scan_index, - true); - scan_index++; + return scan_index; +} + +static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) +{ + struct device_node *node = indio_dev->dev.of_node; + struct stm32_adc *adc = iio_priv(indio_dev); + const struct stm32_adc_info *adc_info = adc->cfg->adc_info; + struct iio_chan_spec *channels; + int scan_index = 0, num_channels = 0, ret, i; + u32 smp = 0; + + ret = stm32_adc_get_legacy_chan_count(indio_dev, adc); + if (ret < 0) + return ret; + num_channels = ret; + + if (!num_channels) { + dev_err(&indio_dev->dev, "No channels configured\n"); + return -ENODATA; } + if (num_channels > adc_info->max_channels) { + dev_err(&indio_dev->dev, "Channel number [%d] exceeds %d\n", + num_channels, adc_info->max_channels); + return -EINVAL; + } + + /* Optional sample time is provided either for each, or all channels */ + ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs"); + if (ret > 1 && ret != num_channels) { + dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n"); + return -EINVAL; + } + + if (timestamping) + num_channels++; + + channels = devm_kcalloc(&indio_dev->dev, num_channels, + sizeof(struct iio_chan_spec), GFP_KERNEL); + if (!channels) + return -ENOMEM; + + ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels); + if (ret < 0) + return ret; + scan_index = ret; + for (i = 0; i < scan_index; i++) { /* * Using of_property_read_u32_index(), smp value will only be From patchwork Wed Sep 8 15:54:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier MOYSAN X-Patchwork-Id: 12481445 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B95DFC4321E for ; Wed, 8 Sep 2021 15:55:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 972BC6113D for ; Wed, 8 Sep 2021 15:55:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352162AbhIHP4l (ORCPT ); Wed, 8 Sep 2021 11:56:41 -0400 Received: from mx07-00178001.pphosted.com ([185.132.182.106]:49650 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349591AbhIHP4j (ORCPT ); Wed, 8 Sep 2021 11:56:39 -0400 Received: from pps.filterd (m0241204.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.0.43) with SMTP id 188FpDvj017933; Wed, 8 Sep 2021 17:55:02 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=selector1; bh=e/oa1unCRWL4AroRZ8b6CGYEbaQjckTlJaMT/ZZmzuI=; b=geyj3Vm057r+eAGIcs/KMLLh259gGdN2hQBvWyMUxLBm/1JXRO0nXyoVf8LG5+YsZ5WR c938NpeKJYnBL8fGbCZ82tBj59jQ2e1Ux8t3WxiBSNMOD65zwJmJeaMvbGPNIGT/11TB wASZwqlD5Rsl0Go2JeVVDoJ1nGjBvcFCV+IpQC1dW/uQNP1FXF0HyQxGShKo8hlgwiFW 8oGq1OaZ7zpEGyn31fvtt6p6QO4PVDf4egE3PslL53mB4DoYEItfc6faAhJ7LoARWjbk pVJNflo70Nn9joggXcnN/0YykV4zwDZ4oghpVf20+S8hfb+gVEJ3yFPTlu0t19rUFjSj vw== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3axwtygupq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 Sep 2021 17:55:02 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 5F83F100034; Wed, 8 Sep 2021 17:55:02 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag1node3.st.com [10.75.127.3]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 4CA8D2203A5; Wed, 8 Sep 2021 17:55:02 +0200 (CEST) Received: from localhost (10.75.127.51) by SFHDAG1NODE3.st.com (10.75.127.3) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 8 Sep 2021 17:55:01 +0200 From: Olivier Moysan To: Alexandre Torgue , Arnaud Pouliquen , Fabrice Gasnier , Jonathan Cameron , Lars-Peter Clausen , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , , Subject: [PATCH 4/7] iio: adc: stm32-adc: add support of generic channels binding Date: Wed, 8 Sep 2021 17:54:49 +0200 Message-ID: <20210908155452.25458-5-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210908155452.25458-1-olivier.moysan@foss.st.com> References: <20210908155452.25458-1-olivier.moysan@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.51] X-ClientProxiedBy: SFHDAG1NODE2.st.com (10.75.127.2) To SFHDAG1NODE3.st.com (10.75.127.3) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-08_06,2021-09-07_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add support of generic IIO channel binding: ./devicetree/bindings/iio/adc/adc.yaml Keep support of st,adc-channels and st,adc-diff-channels for backward compatibility. Signed-off-by: Olivier Moysan --- drivers/iio/adc/stm32-adc.c | 99 +++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 9 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 2f137d14f141..ae4a314854f7 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -35,7 +35,7 @@ #define STM32H7_BOOST_CLKRATE 20000000UL #define STM32_ADC_CH_MAX 20 /* max number of channels */ -#define STM32_ADC_CH_SZ 10 /* max channel name size */ +#define STM32_ADC_CH_SZ 16 /* max channel name size */ #define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */ #define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */ #define STM32_ADC_TIMEOUT_US 100000 @@ -1732,6 +1732,11 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm num_channels += ret; } + if (!num_channels) { + dev_err(indio_dev->dev.parent, "No channel found\n"); + return -ENODATA; + } + return num_channels; } @@ -1792,6 +1797,73 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev, return scan_index; } +static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, + struct stm32_adc *adc, + struct iio_chan_spec *channels) +{ + struct device_node *node = indio_dev->dev.of_node; + const struct stm32_adc_info *adc_info = adc->cfg->adc_info; + struct device_node *child; + const char *name; + int val, scan_index = 0, ret; + bool differential; + u32 vin[2]; + + for_each_available_child_of_node(node, child) { + ret = of_property_read_u32(child, "reg", &val); + if (ret) { + dev_err(&indio_dev->dev, "Missing channel index %d\n", ret); + goto err; + } + + ret = of_property_read_string(child, "label", &name); + /* label is optional */ + if (!ret) { + if (strlen(name) >= STM32_ADC_CH_SZ) { + dev_err(&indio_dev->dev, "Label %s exceeds %d characters\n", + name, STM32_ADC_CH_SZ); + return -EINVAL; + } + strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ); + } else if (ret != -EINVAL) { + dev_err(&indio_dev->dev, "Invalid label %d\n", ret); + goto err; + } + + if (val >= adc_info->max_channels) { + dev_err(&indio_dev->dev, "Invalid channel %d\n", val); + ret = -EINVAL; + goto err; + } + + differential = false; + ret = of_property_read_u32_array(child, "diff-channels", vin, 2); + /* diff-channels is optional */ + if (!ret) { + differential = true; + if (vin[0] != val || vin[1] >= adc_info->max_channels) { + dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n", + vin[0], vin[1]); + goto err; + } + } else if (ret != -EINVAL) { + dev_err(&indio_dev->dev, "Invalid diff-channels property %d\n", ret); + goto err; + } + + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val, + vin[1], scan_index, differential); + scan_index++; + } + + return scan_index; + +err: + of_node_put(child); + + return ret; +} + static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) { struct device_node *node = indio_dev->dev.of_node; @@ -1800,15 +1872,21 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) struct iio_chan_spec *channels; int scan_index = 0, num_channels = 0, ret, i; u32 smp = 0; + bool legacy = false; - ret = stm32_adc_get_legacy_chan_count(indio_dev, adc); - if (ret < 0) - return ret; - num_channels = ret; - + num_channels = of_get_available_child_count(node); + /* + * If no channels have been found, fallback to channels legacy properties. + * Legacy channel properties will be ignored, if some channels are + * already defined using the standard binding. + */ if (!num_channels) { - dev_err(&indio_dev->dev, "No channels configured\n"); - return -ENODATA; + ret = stm32_adc_get_legacy_chan_count(indio_dev, adc); + if (ret < 0) + return ret; + + legacy = true; + num_channels = ret; } if (num_channels > adc_info->max_channels) { @@ -1832,7 +1910,10 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) if (!channels) return -ENOMEM; - ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels); + if (legacy) + ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels); + else + ret = stm32_adc_generic_chan_init(indio_dev, adc, channels); if (ret < 0) return ret; scan_index = ret; From patchwork Wed Sep 8 15:54:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier MOYSAN X-Patchwork-Id: 12481449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C7E9AC4167D for ; Wed, 8 Sep 2021 15:55:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9DCFF61041 for ; Wed, 8 Sep 2021 15:55:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352191AbhIHP4m (ORCPT ); Wed, 8 Sep 2021 11:56:42 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:55204 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1349717AbhIHP4j (ORCPT ); Wed, 8 Sep 2021 11:56:39 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.0.43) with SMTP id 188FpEW5005684; Wed, 8 Sep 2021 17:55:03 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=selector1; bh=GCSSvY8XrvSItV3HUoBzc89zbZmgPgQTdQFSowWleSU=; b=v1jIBtQEtftF/ryoalfrxM6av1mz+AIVgC2mfMc3ec9Sf+5dqORJkeRkxY0O2N/F2YPz CESLcS0xbz4Wr4HfRYrk//wWvjljYF7HiD5ez/pqcZg/9HDc06OzGrk5eQE1Zvm0ZQRc kWBy7oqTc11t1ZG6MqKhBpX3rYcDser6gJgIkiDlKtWCI0Kach/6qQikXbsxXhWYbtjA ngSdug8IVF7gurdHKJSbi/H+fsFsnxChBNtPhgAlOFDrDeEu2lGylOWBUvU2XhBsMT6h 7t5LRdV2zq6xvIExtxV8JuCqwF729ksi+hPVa0/sxnbmVpCd2AWlNkFa2mr3C+hFR5e9 IA== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3axtha2b80-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 Sep 2021 17:55:03 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6001310002A; Wed, 8 Sep 2021 17:55:03 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag1node3.st.com [10.75.127.3]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 44C15229A9E; Wed, 8 Sep 2021 17:55:03 +0200 (CEST) Received: from localhost (10.75.127.50) by SFHDAG1NODE3.st.com (10.75.127.3) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 8 Sep 2021 17:55:02 +0200 From: Olivier Moysan To: Alexandre Torgue , Arnaud Pouliquen , Fabrice Gasnier , Jonathan Cameron , Lars-Peter Clausen , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , , Subject: [PATCH 5/7] iio: adc: stm32-adc: add support of internal channels Date: Wed, 8 Sep 2021 17:54:50 +0200 Message-ID: <20210908155452.25458-6-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210908155452.25458-1-olivier.moysan@foss.st.com> References: <20210908155452.25458-1-olivier.moysan@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.50] X-ClientProxiedBy: SFHDAG2NODE3.st.com (10.75.127.6) To SFHDAG1NODE3.st.com (10.75.127.3) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-08_06,2021-09-07_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add support of ADC2 internal channels VDDCORE, VREFINT and VBAT. The reserved label name "vddcore", "vrefint" and "vbat" must be used in Device Tree channel node, to enable the corresponding internal channel. Note: This patch does not provide support of internal channels for F4 and H7. Signed-off-by: Olivier Moysan --- drivers/iio/adc/stm32-adc-core.h | 8 ++ drivers/iio/adc/stm32-adc.c | 123 ++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h index 2322809bfd2f..7c924f463f67 100644 --- a/drivers/iio/adc/stm32-adc-core.h +++ b/drivers/iio/adc/stm32-adc-core.h @@ -102,6 +102,9 @@ #define STM32H7_ADC_CALFACT 0xC4 #define STM32H7_ADC_CALFACT2 0xC8 +/* STM32MP1 - ADC2 instance option register */ +#define STM32MP1_ADC2_OR 0xD0 + /* STM32H7 - common registers for all ADC instances */ #define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00) #define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08) @@ -168,11 +171,16 @@ enum stm32h7_adc_dmngt { #define STM32H7_EOC_MST BIT(2) /* STM32H7_ADC_CCR - bit fields */ +#define STM32H7_VBATEN BIT(24) +#define STM32H7_VREFEN BIT(22) #define STM32H7_PRESC_SHIFT 18 #define STM32H7_PRESC_MASK GENMASK(21, 18) #define STM32H7_CKMODE_SHIFT 16 #define STM32H7_CKMODE_MASK GENMASK(17, 16) +/* STM32MP1_ADC2_OR - bit fields */ +#define STM32MP1_VDDCOREEN BIT(0) + /** * struct stm32_adc_common - stm32 ADC driver common data (for all instances) * @base: control registers base cpu addr diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index ae4a314854f7..ef3d2af98025 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -41,6 +41,7 @@ #define STM32_ADC_TIMEOUT_US 100000 #define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000)) #define STM32_ADC_HW_STOP_DELAY_MS 100 +#define STM32_ADC_CHAN_NONE -1 #define STM32_DMA_BUFFER_SIZE PAGE_SIZE @@ -77,6 +78,29 @@ enum stm32_adc_extsel { STM32_EXT20, }; +enum stm32_adc_int_ch { + STM32_ADC_INT_CH_VDDCORE, + STM32_ADC_INT_CH_VREFINT, + STM32_ADC_INT_CH_VBAT, + STM32_ADC_INT_CH_NB, +}; + +/** + * struct stm32_adc_ic - ADC internal channels + * @name: name of the internal channel + * @idx: internal channel enum index + */ +struct stm32_adc_ic { + const char *name; + u32 idx; +}; + +static const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = { + { "vddcore", STM32_ADC_INT_CH_VDDCORE }, + { "vrefint", STM32_ADC_INT_CH_VREFINT }, + { "vbat", STM32_ADC_INT_CH_VBAT }, +}; + /** * struct stm32_adc_trig_info - ADC trigger info * @name: name of the trigger, corresponding to its source @@ -126,6 +150,9 @@ struct stm32_adc_regs { * @res: resolution selection register & bitfield * @smpr: smpr1 & smpr2 registers offset array * @smp_bits: smpr1 & smpr2 index and bitfields + * @or_vdd: option register & vddcore bitfield + * @ccr_vbat: common register & vbat bitfield + * @ccr_vref: common register & vrefint bitfield */ struct stm32_adc_regspec { const u32 dr; @@ -139,6 +166,9 @@ struct stm32_adc_regspec { const struct stm32_adc_regs res; const u32 smpr[2]; const struct stm32_adc_regs *smp_bits; + const struct stm32_adc_regs or_vdd; + const struct stm32_adc_regs ccr_vbat; + const struct stm32_adc_regs ccr_vref; }; struct stm32_adc; @@ -195,6 +225,7 @@ struct stm32_adc_cfg { * @cal: optional calibration data on some devices * @chan_name: channel name array * @num_diff: number of differential channels + * @int_ch: internal channel indexes array */ struct stm32_adc { struct stm32_adc_common *common; @@ -219,6 +250,7 @@ struct stm32_adc { struct stm32_adc_calib cal; char chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ]; u32 num_diff; + int int_ch[STM32_ADC_INT_CH_NB]; }; struct stm32_adc_diff_channel { @@ -451,6 +483,24 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = { .smp_bits = stm32h7_smp_bits, }; +static const struct stm32_adc_regspec stm32mp1_adc_regspec = { + .dr = STM32H7_ADC_DR, + .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, + .ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE }, + .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC }, + .isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR }, + .sqr = stm32h7_sq, + .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT }, + .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, + STM32H7_EXTSEL_SHIFT }, + .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT }, + .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 }, + .smp_bits = stm32h7_smp_bits, + .or_vdd = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN }, + .ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN }, + .ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN }, +}; + /* * STM32 ADC registers access routines * @adc: stm32 adc instance @@ -579,6 +629,61 @@ static int stm32_adc_hw_start(struct device *dev) return ret; } +static void stm32_adc_int_ch_enable(struct iio_dev *indio_dev) +{ + struct stm32_adc *adc = iio_priv(indio_dev); + u32 i, val, bits = 0, offset = 0; + + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { + if (adc->int_ch[i] == STM32_ADC_CHAN_NONE) + continue; + + switch (i) { + case STM32_ADC_INT_CH_VDDCORE: + dev_dbg(&indio_dev->dev, "Enable VDDCore\n"); + stm32_adc_set_bits(adc, adc->cfg->regs->or_vdd.reg, + adc->cfg->regs->or_vdd.mask); + break; + case STM32_ADC_INT_CH_VREFINT: + dev_dbg(&indio_dev->dev, "Enable VREFInt\n"); + offset = adc->cfg->regs->ccr_vref.reg; + bits |= adc->cfg->regs->ccr_vref.mask; + break; + case STM32_ADC_INT_CH_VBAT: + dev_dbg(&indio_dev->dev, "Enable VBAT\n"); + offset = adc->cfg->regs->ccr_vbat.reg; + bits |= adc->cfg->regs->ccr_vbat.mask; + break; + } + } + + if (bits) { + val = readl_relaxed(adc->common->base + offset); + val |= bits; + writel_relaxed(val, adc->common->base + offset); + } +} + +static void stm32_adc_int_ch_disable(struct stm32_adc *adc) +{ + u32 val, bits, offset, i; + + stm32_adc_clr_bits(adc, adc->cfg->regs->or_vdd.reg, + adc->cfg->regs->or_vdd.mask); + + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { + if (adc->int_ch[i] != STM32_ADC_CHAN_NONE) { + offset = adc->cfg->regs->ccr_vref.reg; + bits = adc->cfg->regs->ccr_vref.mask | + adc->cfg->regs->ccr_vbat.mask; + val = readl_relaxed(adc->common->base + offset); + val &= ~bits; + writel_relaxed(bits, adc->common->base + offset); + break; + } + } +} + /** * stm32f4_adc_start_conv() - Start conversions for regular channels. * @indio_dev: IIO device instance @@ -947,11 +1052,13 @@ static int stm32h7_adc_prepare(struct iio_dev *indio_dev) goto pwr_dwn; calib = ret; + stm32_adc_int_ch_enable(indio_dev); + stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel); ret = stm32h7_adc_enable(indio_dev); if (ret) - goto pwr_dwn; + goto ch_disable; /* Either restore or read calibration result for future reference */ if (calib) @@ -967,6 +1074,8 @@ static int stm32h7_adc_prepare(struct iio_dev *indio_dev) disable: stm32h7_adc_disable(indio_dev); +ch_disable: + stm32_adc_int_ch_disable(adc); pwr_dwn: stm32h7_adc_enter_pwr_down(adc); @@ -978,6 +1087,7 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) struct stm32_adc *adc = iio_priv(indio_dev); stm32h7_adc_disable(indio_dev); + stm32_adc_int_ch_disable(adc); stm32h7_adc_enter_pwr_down(adc); } @@ -1805,10 +1915,13 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, const struct stm32_adc_info *adc_info = adc->cfg->adc_info; struct device_node *child; const char *name; - int val, scan_index = 0, ret; + int val, scan_index = 0, ret, i; bool differential; u32 vin[2]; + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) + adc->int_ch[i] = STM32_ADC_CHAN_NONE; + for_each_available_child_of_node(node, child) { ret = of_property_read_u32(child, "reg", &val); if (ret) { @@ -1825,6 +1938,10 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, return -EINVAL; } strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ); + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { + if (!strncmp(stm32_adc_ic[i].name, name, STM32_ADC_CH_SZ)) + adc->int_ch[i] = val; + } } else if (ret != -EINVAL) { dev_err(&indio_dev->dev, "Invalid label %d\n", ret); goto err; @@ -2223,7 +2340,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { }; static const struct stm32_adc_cfg stm32mp1_adc_cfg = { - .regs = &stm32h7_adc_regspec, + .regs = &stm32mp1_adc_regspec, .adc_info = &stm32h7_adc_info, .trigs = stm32h7_adc_trigs, .has_vregready = true, From patchwork Wed Sep 8 15:54:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier MOYSAN X-Patchwork-Id: 12481451 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D5BDC433EF for ; Wed, 8 Sep 2021 15:55:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 832966113C for ; Wed, 8 Sep 2021 15:55:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352265AbhIHP5B (ORCPT ); Wed, 8 Sep 2021 11:57:01 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:55354 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1349719AbhIHP4x (ORCPT ); Wed, 8 Sep 2021 11:56:53 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.0.43) with SMTP id 188FpQ8Z005816; Wed, 8 Sep 2021 17:55:26 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=selector1; bh=BG/Ki6ZeekgfBPE/MfIcKhxRwcZEyXIAfl11Ncp86lk=; b=3+k4l0ktw1rfzTwgPPsVvtPLqfxnRWsjdSVy/exxCsaJE9YXbj7Yx2ajm2GbWjfmoXeP q9y6JCzTfZJrnTY4++eY+g/szFU93Xp4zHb3RSnyHHXTLRxPMt9UvMrBoO3qlLOrPOzW ctSgnchZ3IjE8gPoX11L6LFZ0bhndxw59aVBYKh+nF56vwfV8KjGzqJpELF6OcPjr2gm SCli++QlCGWpxZNuXwM21SJ7XZrT65IUfZKSchIB7t9i9WmaLWfKu06oWy76fXbSazSu 3VpuXcHvOOK1nYfCJU/jxey4LUUrrVZK1McynXaaWru3qs/dl5j1fQvXE7f2vOcGUYhK Zw== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3axtha2b9f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 Sep 2021 17:55:26 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 43692100034; Wed, 8 Sep 2021 17:55:25 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag1node3.st.com [10.75.127.3]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 32E562203DE; Wed, 8 Sep 2021 17:55:25 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG1NODE3.st.com (10.75.127.3) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 8 Sep 2021 17:55:24 +0200 From: Olivier Moysan To: Alexandre Torgue , Arnaud Pouliquen , Fabrice Gasnier , Jonathan Cameron , Lars-Peter Clausen , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , , Subject: [PATCH 6/7] iio: adc: stm32-adc: add vrefint calibration support Date: Wed, 8 Sep 2021 17:54:51 +0200 Message-ID: <20210908155452.25458-7-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210908155452.25458-1-olivier.moysan@foss.st.com> References: <20210908155452.25458-1-olivier.moysan@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG2NODE1.st.com (10.75.127.4) To SFHDAG1NODE3.st.com (10.75.127.3) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-08_06,2021-09-07_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add support of vrefint calibration. If a channel is labeled as vrefint, get vrefint calibration from non volatile memory for this channel. A conversion on vrefint channel allows to update scale factor according to vrefint deviation, compared to vrefint calibration value. Signed-off-by: Olivier Moysan --- drivers/iio/adc/stm32-adc.c | 88 ++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index ef3d2af98025..9e52a7de9b16 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000)) #define STM32_ADC_HW_STOP_DELAY_MS 100 #define STM32_ADC_CHAN_NONE -1 +#define STM32_ADC_VREFINT_VOLTAGE 3300 #define STM32_DMA_BUFFER_SIZE PAGE_SIZE @@ -79,6 +81,7 @@ enum stm32_adc_extsel { }; enum stm32_adc_int_ch { + STM32_ADC_INT_CH_NONE = -1, STM32_ADC_INT_CH_VDDCORE, STM32_ADC_INT_CH_VREFINT, STM32_ADC_INT_CH_VBAT, @@ -137,6 +140,16 @@ struct stm32_adc_regs { int shift; }; +/** + * struct stm32_adc_vrefint - stm32 ADC internal reference voltage data + * @vrefint_cal: vrefint calibration value from nvmem + * @vrefint_data: vrefint actual value + */ +struct stm32_adc_vrefint { + u32 vrefint_cal; + u32 vrefint_data; +}; + /** * struct stm32_adc_regspec - stm32 registers definition * @dr: data register offset @@ -186,6 +199,7 @@ struct stm32_adc; * @unprepare: optional unprepare routine (disable, power-down) * @irq_clear: routine to clear irqs * @smp_cycles: programmable sampling time (ADC clock cycles) + * @ts_vrefint_ns: vrefint minimum sampling time in ns */ struct stm32_adc_cfg { const struct stm32_adc_regspec *regs; @@ -199,6 +213,7 @@ struct stm32_adc_cfg { void (*unprepare)(struct iio_dev *); void (*irq_clear)(struct iio_dev *indio_dev, u32 msk); const unsigned int *smp_cycles; + const unsigned int ts_vrefint_ns; }; /** @@ -223,6 +238,7 @@ struct stm32_adc_cfg { * @pcsel: bitmask to preselect channels on some devices * @smpr_val: sampling time settings (e.g. smpr1 / smpr2) * @cal: optional calibration data on some devices + * @vrefint: internal reference voltage data * @chan_name: channel name array * @num_diff: number of differential channels * @int_ch: internal channel indexes array @@ -248,6 +264,7 @@ struct stm32_adc { u32 pcsel; u32 smpr_val[2]; struct stm32_adc_calib cal; + struct stm32_adc_vrefint vrefint; char chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ]; u32 num_diff; int int_ch[STM32_ADC_INT_CH_NB]; @@ -1331,15 +1348,35 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, ret = stm32_adc_single_conv(indio_dev, chan, val); else ret = -EINVAL; + + /* If channel mask corresponds to vrefint, store data */ + if (adc->int_ch[STM32_ADC_INT_CH_VREFINT] == chan->channel) + adc->vrefint.vrefint_data = *val; + iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: if (chan->differential) { - *val = adc->common->vref_mv * 2; + if (adc->vrefint.vrefint_data && + adc->vrefint.vrefint_cal) { + *val = STM32_ADC_VREFINT_VOLTAGE * 2 * + adc->vrefint.vrefint_cal / + adc->vrefint.vrefint_data; + } else { + *val = adc->common->vref_mv * 2; + } *val2 = chan->scan_type.realbits; } else { - *val = adc->common->vref_mv; + /* Use vrefint data if available */ + if (adc->vrefint.vrefint_data && + adc->vrefint.vrefint_cal) { + *val = STM32_ADC_VREFINT_VOLTAGE * + adc->vrefint.vrefint_cal / + adc->vrefint.vrefint_data; + } else { + *val = adc->common->vref_mv; + } *val2 = chan->scan_type.realbits; } return IIO_VAL_FRACTIONAL_LOG2; @@ -1907,6 +1944,35 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev, return scan_index; } +static int stm32_adc_get_int_ch(struct iio_dev *indio_dev, const char *ch_name, + int chan) +{ + struct stm32_adc *adc = iio_priv(indio_dev); + u16 vrefint; + int i, ret; + + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { + if (!strncmp(stm32_adc_ic[i].name, ch_name, STM32_ADC_CH_SZ)) { + adc->int_ch[i] = chan; + /* If channel is vrefint get calibration data. */ + if (stm32_adc_ic[i].idx == STM32_ADC_INT_CH_VREFINT) { + ret = nvmem_cell_read_u16(&indio_dev->dev, "vrefint", &vrefint); + if (ret && ret != -ENOENT && ret != -EOPNOTSUPP) { + dev_err(&indio_dev->dev, "nvmem access error %d\n", ret); + return ret; + } + if (ret == -ENOENT) + dev_dbg(&indio_dev->dev, + "vrefint calibration not found\n"); + else + adc->vrefint.vrefint_cal = vrefint; + } + } + } + + return 0; +} + static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, struct stm32_adc *adc, struct iio_chan_spec *channels) @@ -1938,10 +2004,9 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, return -EINVAL; } strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ); - for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { - if (!strncmp(stm32_adc_ic[i].name, name, STM32_ADC_CH_SZ)) - adc->int_ch[i] = val; - } + ret = stm32_adc_get_int_ch(indio_dev, name, val); + if (ret) + goto err; } else if (ret != -EINVAL) { dev_err(&indio_dev->dev, "Invalid label %d\n", ret); goto err; @@ -2044,6 +2109,16 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) */ of_property_read_u32_index(node, "st,min-sample-time-nsecs", i, &smp); + + /* + * For vrefint channel, ensure that the sampling time cannot + * be lower than the one specified in the datasheet + */ + if (channels[i].channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT] && + smp < adc->cfg->ts_vrefint_ns) { + smp = adc->cfg->ts_vrefint_ns; + } + /* Prepare sampling time settings */ stm32_adc_smpr_init(adc, channels[i].channel, smp); } @@ -2350,6 +2425,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { .unprepare = stm32h7_adc_unprepare, .smp_cycles = stm32h7_adc_smp_cycles, .irq_clear = stm32h7_adc_irq_clear, + .ts_vrefint_ns = 4300, }; static const struct of_device_id stm32_adc_of_match[] = { From patchwork Wed Sep 8 15:54:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier MOYSAN X-Patchwork-Id: 12481453 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5F314C4332F for ; Wed, 8 Sep 2021 15:55:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4BA6F60232 for ; Wed, 8 Sep 2021 15:55:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352277AbhIHP5D (ORCPT ); Wed, 8 Sep 2021 11:57:03 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:33752 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1349717AbhIHP4z (ORCPT ); Wed, 8 Sep 2021 11:56:55 -0400 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.0.43) with SMTP id 188FpD5a007620; Wed, 8 Sep 2021 17:55:27 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=selector1; bh=VvHoepqjh9lgy+RlZqlNBMzDEwzNhV8nbDRE6/jdGUs=; b=wF/aRBZuNKRNfEeIHceMBnp0PrCCs+NjScRJlEVrPYJs9+ERF2Pmd3BT787tdkjJ3NfN wtN8i/iwUbQTrMx0vV/AdIYQbmG/3b4/LbZyzTgXH8G0iXA149ff7DgsYH4w6vfMZRjP Z4GFmdNN6fv2WjlaW1dLKmijBkbhzc5LeEDW+tQzb0gDpTN5zHdnv1mbzPEWiApYZtIM KInl2Uizv+w9+egygmjgpSR6kAIr/n35py7Jm9kwvna5y3CKJXEwbjMZU6mmf4acQHxB Qo4QVCveBYsjfZscvEvsBJK2OqGX/mRKfpXb4YQbgAN/2hoarhlaO2W/332VbuFm25WJ Zw== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3axt4majjh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 Sep 2021 17:55:27 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 23E5610003B; Wed, 8 Sep 2021 17:55:26 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag1node3.st.com [10.75.127.3]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 1416721F0A7; Wed, 8 Sep 2021 17:55:26 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG1NODE3.st.com (10.75.127.3) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 8 Sep 2021 17:55:25 +0200 From: Olivier Moysan To: Alexandre Torgue , Arnaud Pouliquen , Fabrice Gasnier , Jonathan Cameron , Lars-Peter Clausen , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , , Subject: [PATCH 7/7] iio: adc: stm32-adc: use generic binding for sample-time Date: Wed, 8 Sep 2021 17:54:52 +0200 Message-ID: <20210908155452.25458-8-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210908155452.25458-1-olivier.moysan@foss.st.com> References: <20210908155452.25458-1-olivier.moysan@foss.st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG1NODE2.st.com (10.75.127.2) To SFHDAG1NODE3.st.com (10.75.127.3) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.391,FMLib:17.0.607.475 definitions=2021-09-08_06,2021-09-07_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add st,min-sample-time-nsecs to channel generic binding. Sample time can be defined par channel node. If a channel is configured as differential, the same sample time applies for both inputs. Keep support of legacy st,min-sample-time-nsecs property for backward compatibility. Signed-off-by: Olivier Moysan --- drivers/iio/adc/stm32-adc.c | 75 +++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 9e52a7de9b16..2d52415770b3 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1806,6 +1806,14 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns) u32 period_ns, shift = smpr->shift, mask = smpr->mask; unsigned int smp, r = smpr->reg; + /* + * For vrefint channel, ensure that the sampling time cannot + * be lower than the one specified in the datasheet + */ + if (channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT] && + smp_ns < adc->cfg->ts_vrefint_ns) + smp_ns = adc->cfg->ts_vrefint_ns; + /* Determine sampling time (ADC clock cycles) */ period_ns = NSEC_PER_SEC / adc->common->rate; for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++) @@ -1884,6 +1892,13 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm return -ENODATA; } + /* Optional sample time is provided either for each, or all channels */ + ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs"); + if (ret > 1 && ret != num_channels) { + dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n"); + return -EINVAL; + } + return num_channels; } @@ -1899,6 +1914,7 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev, int scan_index = 0, val, ret, i; struct property *prop; const __be32 *cur; + u32 smp = 0; if (num_diff) { ret = of_property_read_u32_array(node, "st,adc-diff-channels", @@ -1941,6 +1957,19 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev, scan_index++; } + for (i = 0; i < scan_index; i++) { + /* + * Using of_property_read_u32_index(), smp value will only be + * modified if valid u32 value can be decoded. This allows to + * get either no value, 1 shared value for all indexes, or one + * value per channel. + */ + of_property_read_u32_index(node, "st,min-sample-time-nsecs", i, &smp); + + /* Prepare sampling time settings */ + stm32_adc_smpr_init(adc, channels[i].channel, smp); + } + return scan_index; } @@ -2035,6 +2064,19 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val, vin[1], scan_index, differential); + + ret = of_property_read_u32(child, "st,min-sample-time-nsecs", &val); + /* st,min-sample-time-nsecs is optional */ + if (!ret) { + stm32_adc_smpr_init(adc, channels[scan_index].channel, val); + if (vin[1]) + stm32_adc_smpr_init(adc, vin[1], val); + } else if (ret != -EINVAL) { + dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs property %d\n", + ret); + goto err; + } + scan_index++; } @@ -2052,8 +2094,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) struct stm32_adc *adc = iio_priv(indio_dev); const struct stm32_adc_info *adc_info = adc->cfg->adc_info; struct iio_chan_spec *channels; - int scan_index = 0, num_channels = 0, ret, i; - u32 smp = 0; + int scan_index = 0, num_channels = 0, ret; bool legacy = false; num_channels = of_get_available_child_count(node); @@ -2077,13 +2118,6 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) return -EINVAL; } - /* Optional sample time is provided either for each, or all channels */ - ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs"); - if (ret > 1 && ret != num_channels) { - dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n"); - return -EINVAL; - } - if (timestamping) num_channels++; @@ -2100,29 +2134,6 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) return ret; scan_index = ret; - for (i = 0; i < scan_index; i++) { - /* - * Using of_property_read_u32_index(), smp value will only be - * modified if valid u32 value can be decoded. This allows to - * get either no value, 1 shared value for all indexes, or one - * value per channel. - */ - of_property_read_u32_index(node, "st,min-sample-time-nsecs", - i, &smp); - - /* - * For vrefint channel, ensure that the sampling time cannot - * be lower than the one specified in the datasheet - */ - if (channels[i].channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT] && - smp < adc->cfg->ts_vrefint_ns) { - smp = adc->cfg->ts_vrefint_ns; - } - - /* Prepare sampling time settings */ - stm32_adc_smpr_init(adc, channels[i].channel, smp); - } - if (timestamping) { struct iio_chan_spec *timestamp = &channels[scan_index];