From patchwork Mon Oct 11 15:57:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Moysan X-Patchwork-Id: 12550421 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 06AFEC433F5 for ; Mon, 11 Oct 2021 15:58:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DF46760551 for ; Mon, 11 Oct 2021 15:58:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235938AbhJKQA1 (ORCPT ); Mon, 11 Oct 2021 12:00:27 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:48504 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S231766AbhJKQAZ (ORCPT ); Mon, 11 Oct 2021 12:00:25 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19B9etq0022265; Mon, 11 Oct 2021 17:58: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=ehzqaetFwAxKeidlDcFPfHTrZiO8cJwJfarmE2gZgmk=; b=PTbIiJdNjG4ugdJyVseHHMXmHt/vSTWdZa43yhov8q++U3PSp0xBtyRouJGbQ4Vi9tDx X/s2xmtGUmczrcyfRgdxaf2Jl8r4YoLTqDcY7atWDwCHJ7g8xQNDK7T0g65SP8irkKbg GCuWfH4m2JmkM1gj66qwtesSQu7l+hsl06MtQTMdhxYe9mipCkCMTFViCIlp7PiFYzCs CR0X+CbF95eEfj7EVLO/MqoCOSCaNGCwP+NHi8rxK5WJAJ0ssl+CSEXlgfe8B9Gr8kQV 1cWSv+wSeh0yGgPi3EpPah6Qr4bbQF5gGZGWEPLkqaGR6MaFae6qipHSWPK6NCXWHQvz aQ== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3bmdxrkunn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 Oct 2021 17:58: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 33BE9100039; Mon, 11 Oct 2021 17:58:01 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 2B7BF231DE0; Mon, 11 Oct 2021 17:58:01 +0200 (CEST) Received: from localhost (10.75.127.51) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Mon, 11 Oct 2021 17:58:00 +0200 From: Olivier Moysan To: Alexandre Torgue , Fabrice Gasnier , Jonathan Cameron , "Lars-Peter Clausen" , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , Subject: [PATCH v4 1/7] dt-bindings: iio: stm32-adc: add generic channel binding Date: Mon, 11 Oct 2021 17:57:11 +0200 Message-ID: <20211011155717.1594-2-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211011155717.1594-1-olivier.moysan@foss.st.com> References: <20211011155717.1594-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 SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-11_05,2021-10-11_01,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 Reviewed-by: Fabrice Gasnier --- .../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..ece1864fdcd9 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: @@ -256,6 +262,7 @@ patternProperties: - 20 channels, numbered from 0 to 19 (for in0..in19) on stm32h7 and stm32mp1. $ref: /schemas/types.yaml#/definitions/uint32-array + deprecated: true st,adc-diff-channels: description: | @@ -265,7 +272,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 @@ -279,6 +288,7 @@ patternProperties: "vinn" indicates negative input number minimum: 0 maximum: 19 + deprecated: true st,min-sample-time-nsecs: description: @@ -289,6 +299,42 @@ patternProperties: list, to set sample time resp. for all channels, or independently for each channel. $ref: /schemas/types.yaml#/definitions/uint32-array + deprecated: true + + 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-ns: + 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 + + additionalProperties: false allOf: - if: @@ -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 Mon Oct 11 15:57:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Moysan X-Patchwork-Id: 12550417 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B30BCC433FE for ; Mon, 11 Oct 2021 15:58:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8C06960F3A for ; Mon, 11 Oct 2021 15:58:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234661AbhJKQA0 (ORCPT ); Mon, 11 Oct 2021 12:00:26 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:48500 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S232311AbhJKQAZ (ORCPT ); Mon, 11 Oct 2021 12:00:25 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19B9t3UM022181; Mon, 11 Oct 2021 17:58: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=itZ2wQMByi0rvs2cFwdlXR8Qz1+hdcRuOmzaZez/dBU=; b=UA95L+k6tz2dVf/PyA2tr6tlos2qCziQsMBBVb5FvvLiZFkESHM2P8crlpQpaEaRtvw5 xhWtErl6RN71tZlWACPunGIcOQAvpyy6fJ1R9tLuwBcfCdNNLp2w+WmGl9hogeGlObB8 ROrq9am0Dggsex/igMgmWh1qUulb2URaPis+fLoMjGPW2j1pj+wsI51jkj4ZaTLaqBIM 77KVsJf6gMJl7UJCj3SmEn0viu3yHM+59+E8VNX/HYW4QLr21JYcoN+QU+Q3hCmgPmVf J4JWBUfJzdFTQYhNNd/tYUNa35kNdCB3FbiGqqvvev225im26OSobFsxI7ItksGKwUGD oA== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3bmdxrkunu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 Oct 2021 17:58: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 9B11610002A; Mon, 11 Oct 2021 17:58:02 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 8F1B7231DE1; Mon, 11 Oct 2021 17:58:02 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Mon, 11 Oct 2021 17:58:01 +0200 From: Olivier Moysan To: Alexandre Torgue , Fabrice Gasnier , Jonathan Cameron , "Lars-Peter Clausen" , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , Subject: [PATCH v4 2/7] dt-bindings: iio: stm32-adc: add nvmem support for vrefint internal channel Date: Mon, 11 Oct 2021 17:57:12 +0200 Message-ID: <20211011155717.1594-3-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211011155717.1594-1-olivier.moysan@foss.st.com> References: <20211011155717.1594-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 SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-11_05,2021-10-11_01,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 Reviewed-by: Fabrice Gasnier 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 ece1864fdcd9..7dfdddee8de0 100644 --- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml @@ -301,6 +301,14 @@ patternProperties: $ref: /schemas/types.yaml#/definitions/uint32-array deprecated: true + 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 Mon Oct 11 15:57:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Moysan X-Patchwork-Id: 12550427 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD786C433F5 for ; Mon, 11 Oct 2021 15:58:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A71FF60EB1 for ; Mon, 11 Oct 2021 15:58:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231766AbhJKQAy (ORCPT ); Mon, 11 Oct 2021 12:00:54 -0400 Received: from mx07-00178001.pphosted.com ([185.132.182.106]:41956 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234563AbhJKQAt (ORCPT ); Mon, 11 Oct 2021 12:00:49 -0400 Received: from pps.filterd (m0241204.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19BCW230020232; Mon, 11 Oct 2021 17:58:04 +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=9rOZYlkf5voByr7hgqT920hjGkGE84+icfZuj16RzCA=; b=at7bDq1fHa3KyKTfNBtMNf8PmY5VwqgtKwHfRikquq2r79ZX841UM4UktHX9J5RW3Qvv PXJjl6ihiCDMA8hQ2ByuxOHtJDOcb7XErcTJHGQLP210b+RBF2OR00lm/N1jc+dsFo7w 9r1mdybQv9EY8I9+CRgCOrNocQCgUPe/Dd4kZ7E9ICdjKe+uz7qlfJyeLsx4YA+BtjQR RUhUEemBlFoBy9GwKbtchLD6aIVk9sO7SqEmTLraK4BNfuwZxPuueRtChZz8agj8t6hy UgMlqhnbk86yQrEvuZt1h24WBm0vNJgbROijMbBVvbbs45FyCxBVlVCfktfbMimGRKV5 zg== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3bmgquav6d-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 Oct 2021 17:58:04 +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 14C7310002A; Mon, 11 Oct 2021 17:58:04 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 0A2EB231DE0; Mon, 11 Oct 2021 17:58:04 +0200 (CEST) Received: from localhost (10.75.127.51) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Mon, 11 Oct 2021 17:58:03 +0200 From: Olivier Moysan To: Alexandre Torgue , Fabrice Gasnier , Jonathan Cameron , "Lars-Peter Clausen" , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , Subject: [PATCH v4 3/7] iio: adc: stm32-adc: split channel init into several routines Date: Mon, 11 Oct 2021 17:57:13 +0200 Message-ID: <20211011155717.1594-4-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211011155717.1594-1-olivier.moysan@foss.st.com> References: <20211011155717.1594-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 SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-11_05,2021-10-11_01,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 Reviewed-by: Fabrice Gasnier --- 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 Mon Oct 11 15:57:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Moysan X-Patchwork-Id: 12550423 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85D50C4332F for ; Mon, 11 Oct 2021 15:58:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6FAA960EB1 for ; Mon, 11 Oct 2021 15:58:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236428AbhJKQAa (ORCPT ); Mon, 11 Oct 2021 12:00:30 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:43846 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S234439AbhJKQA1 (ORCPT ); Mon, 11 Oct 2021 12:00:27 -0400 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19BFw3Ze022059; Mon, 11 Oct 2021 17:58:05 +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=CT5zbzBiiSRHC6LhkJDSwTwmipMVPrFZ/bhglUOKZt4=; b=gn4wXRJe63usGKIbEDEo0ePKzk2i5hk+tDH+5EhOxZ/jHZVjIzLuI7A3fJyrVJE9H2Ca DfHOVaHXc2voAVTwjjQ6sQERnsi6oBjk3Q0z0k9t1nL3Kzjs3l8OdFsnFl34zo7CQAEo 3pvVKHH6lfCRs4yX/TPNv0fJugCa1xJDWLINYZh60B8EW+GFhnk4n/k1531UKbCxRhBR TUcG7L97Xw7uOoYN1TJCadC9UN84vYnAPG4iNuM3wYAgMuvs3rjQNXMAtUHdafF84AYU pjbBBsv+wrThnsbdpz86ZkOkt68HTnomIVtxLe0xzi4Gxe2DhkZ//Q4KdbIW9h3pg0N/ Dw== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3bmd35v2yh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 Oct 2021 17:58:05 +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 5B18F10002A; Mon, 11 Oct 2021 17:58:05 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 533D3231DE0; Mon, 11 Oct 2021 17:58:05 +0200 (CEST) Received: from localhost (10.75.127.51) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Mon, 11 Oct 2021 17:58:04 +0200 From: Olivier Moysan To: Alexandre Torgue , Fabrice Gasnier , Jonathan Cameron , "Lars-Peter Clausen" , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , Subject: [PATCH v4 4/7] iio: adc: stm32-adc: add support of generic channels binding Date: Mon, 11 Oct 2021 17:57:14 +0200 Message-ID: <20211011155717.1594-5-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211011155717.1594-1-olivier.moysan@foss.st.com> References: <20211011155717.1594-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 SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-11_05,2021-10-11_01,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 Reviewed-by: Fabrice Gasnier --- drivers/iio/adc/stm32-adc.c | 95 +++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 2f137d14f141..85d09cbd41ae 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 @@ -1792,6 +1792,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 +1867,22 @@ 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. */ if (!num_channels) { - dev_err(&indio_dev->dev, "No channels configured\n"); - return -ENODATA; + legacy = true; + + ret = stm32_adc_get_legacy_chan_count(indio_dev, adc); + if (!ret) { + dev_err(indio_dev->dev.parent, "No channel found\n"); + return -ENODATA; + } else if (ret < 0) { + return ret; + } + + num_channels = ret; } if (num_channels > adc_info->max_channels) { @@ -1832,7 +1906,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 Mon Oct 11 15:57:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Moysan X-Patchwork-Id: 12550425 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D22D8C433FE for ; Mon, 11 Oct 2021 15:58:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C179960EBB for ; Mon, 11 Oct 2021 15:58:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236721AbhJKQAb (ORCPT ); Mon, 11 Oct 2021 12:00:31 -0400 Received: from mx07-00178001.pphosted.com ([185.132.182.106]:41740 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236128AbhJKQAa (ORCPT ); Mon, 11 Oct 2021 12:00:30 -0400 Received: from pps.filterd (m0241204.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19BCVNn4020055; Mon, 11 Oct 2021 17:58:06 +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=NkmHfnL+jynPd7YVXCwoowRax6yqbL8FZy/ZvX3tZeM=; b=ArdzC9lju9qZQkvC56MvXP3Jb2IcC6IpFlIECLBjfSc9X0Ng77Zx0qRKGHJKKZa/iNaW ME+YTUjzm+6OFgFE6FnYTFf0E2VpIOxG0cbcAzh8rGIeMRb/5ABTMGcSLwaGMBhRHBFw 2KC9jSr6niLqyXfDlbnPf4lY//l8uum4dNa4lLuvXCaiWel6eahkiQVJy5PS8ZVa75UC WcuLrhAQzP8iJWgQxDxFx1bufWObXLYgHccw0EV0fbFRj6DCfRqShfyxvHpaL/muLZ8N zKTBkQHlBCQedQWijfyBVXUIlBi/vGxdqcAoV3Ixn9BwQt+upj+vCZYsoL46sULnrNwS 6g== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 3bmgquav6q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 11 Oct 2021 17:58:06 +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 F0FAD100038; Mon, 11 Oct 2021 17:58:05 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id E7DE0231DE0; Mon, 11 Oct 2021 17:58:05 +0200 (CEST) Received: from localhost (10.75.127.50) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Mon, 11 Oct 2021 17:58:05 +0200 From: Olivier Moysan To: Alexandre Torgue , Fabrice Gasnier , Jonathan Cameron , "Lars-Peter Clausen" , Maxime Coquelin , Olivier Moysan , Rob Herring CC: , , , , Subject: [PATCH v4 5/7] iio: adc: stm32-adc: add support of internal channels Date: Mon, 11 Oct 2021 17:57:15 +0200 Message-ID: <20211011155717.1594-6-olivier.moysan@foss.st.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211011155717.1594-1-olivier.moysan@foss.st.com> References: <20211011155717.1594-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 SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-11_05,2021-10-11_01,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 Reviewed-by: Fabrice Gasnier --- drivers/iio/adc/stm32-adc-core.c | 1 + drivers/iio/adc/stm32-adc-core.h | 10 +++ drivers/iio/adc/stm32-adc.c | 138 ++++++++++++++++++++++++++++++- 3 files changed, 146 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index c088cb990193..b6e18eb101f7 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -659,6 +659,7 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->cfg = (const struct stm32_adc_priv_cfg *) of_match_device(dev->driver->of_match_table, dev)->data; + spin_lock_init(&priv->common.lock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->common.base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h index 2322809bfd2f..faedf7a49555 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,23 +171,30 @@ 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 * @phys_base: control registers base physical addr * @rate: clock rate used for analog circuitry * @vref_mv: vref voltage (mv) + * @lock: spinlock */ struct stm32_adc_common { void __iomem *base; phys_addr_t phys_base; unsigned long rate; int vref_mv; + spinlock_t lock; /* lock for common register */ }; #endif diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 85d09cbd41ae..943ca03f4d31 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -77,6 +77,30 @@ enum stm32_adc_extsel { STM32_EXT20, }; +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, + 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 @@ -489,6 +539,14 @@ static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits) spin_unlock_irqrestore(&adc->lock, flags); } +static void stm32_adc_set_bits_common(struct stm32_adc *adc, u32 reg, u32 bits) +{ + spin_lock(&adc->common->lock); + writel_relaxed(readl_relaxed(adc->common->base + reg) | bits, + adc->common->base + reg); + spin_unlock(&adc->common->lock); +} + static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits) { unsigned long flags; @@ -498,6 +556,14 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits) spin_unlock_irqrestore(&adc->lock, flags); } +static void stm32_adc_clr_bits_common(struct stm32_adc *adc, u32 reg, u32 bits) +{ + spin_lock(&adc->common->lock); + writel_relaxed(readl_relaxed(adc->common->base + reg) & ~bits, + adc->common->base + reg); + spin_unlock(&adc->common->lock); +} + /** * stm32_adc_conv_irq_enable() - Enable end of conversion interrupt * @adc: stm32 adc instance @@ -579,6 +645,60 @@ 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; + + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { + if (adc->int_ch[i] == STM32_ADC_INT_CH_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"); + stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vref.reg, + adc->cfg->regs->ccr_vref.mask); + break; + case STM32_ADC_INT_CH_VBAT: + dev_dbg(&indio_dev->dev, "Enable VBAT\n"); + stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vbat.reg, + adc->cfg->regs->ccr_vbat.mask); + break; + } + } +} + +static void stm32_adc_int_ch_disable(struct stm32_adc *adc) +{ + u32 i; + + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) { + if (adc->int_ch[i] == STM32_ADC_INT_CH_NONE) + continue; + + switch (i) { + case STM32_ADC_INT_CH_VDDCORE: + stm32_adc_clr_bits(adc, adc->cfg->regs->or_vdd.reg, + adc->cfg->regs->or_vdd.mask); + break; + case STM32_ADC_INT_CH_VREFINT: + stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vref.reg, + adc->cfg->regs->ccr_vref.mask); + break; + case STM32_ADC_INT_CH_VBAT: + stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vbat.reg, + adc->cfg->regs->ccr_vbat.mask); + break; + } + } +} + /** * stm32f4_adc_start_conv() - Start conversions for regular channels. * @indio_dev: IIO device instance @@ -947,11 +1067,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 +1089,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 +1102,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); } @@ -1800,7 +1925,7 @@ 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]; @@ -1820,6 +1945,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; @@ -1869,6 +1998,9 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping) u32 smp = 0; bool legacy = false; + for (i = 0; i < STM32_ADC_INT_CH_NB; i++) + adc->int_ch[i] = STM32_ADC_INT_CH_NONE; + num_channels = of_get_available_child_count(node); /* If no channels have been found, fallback to channels legacy properties. */ if (!num_channels) { @@ -2219,7 +2351,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,