From patchwork Mon Jul 19 08:06:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Billy Tsai X-Patchwork-Id: 480165 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=-16.8 required=3.0 tests=BAYES_00, 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 0D296C12002 for ; Mon, 19 Jul 2021 08:06:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DCC7661164 for ; Mon, 19 Jul 2021 08:06:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235115AbhGSIJE (ORCPT ); Mon, 19 Jul 2021 04:09:04 -0400 Received: from twspam01.aspeedtech.com ([211.20.114.71]:38302 "EHLO twspam01.aspeedtech.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235129AbhGSIJE (ORCPT ); Mon, 19 Jul 2021 04:09:04 -0400 Received: from mail.aspeedtech.com ([192.168.0.24]) by twspam01.aspeedtech.com with ESMTP id 16J7nQi0015320; Mon, 19 Jul 2021 15:49:26 +0800 (GMT-8) (envelope-from billy_tsai@aspeedtech.com) Received: from BillyTsai-pc.aspeed.com (192.168.2.149) by TWMBX02.aspeed.com (192.168.0.24) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 19 Jul 2021 16:05:47 +0800 From: Billy Tsai To: , , , , , , , , , , , , CC: Subject: [v1 1/7] dt-bindings: iio: adc: rename the aspeed adc yaml Date: Mon, 19 Jul 2021 16:06:01 +0800 Message-ID: <20210719080607.28712-2-billy_tsai@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210719080607.28712-1-billy_tsai@aspeedtech.com> References: <20210719080607.28712-1-billy_tsai@aspeedtech.com> MIME-Version: 1.0 X-Originating-IP: [192.168.2.149] X-ClientProxiedBy: TWMBX02.aspeed.com (192.168.0.24) To TWMBX02.aspeed.com (192.168.0.24) X-DNSRBL: X-MAIL: twspam01.aspeedtech.com 16J7nQi0015320 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The aspeed,ast2400-adc.yaml not only descriptor the bindings of ast2400. Rename it to aspeed,adc.yaml for all of the aspeed adc bindings. Signed-off-by: Billy Tsai --- .../bindings/iio/adc/{aspeed,ast2400-adc.yaml => aspeed,adc.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/iio/adc/{aspeed,ast2400-adc.yaml => aspeed,adc.yaml} (100%) diff --git a/Documentation/devicetree/bindings/iio/adc/aspeed,ast2400-adc.yaml b/Documentation/devicetree/bindings/iio/adc/aspeed,adc.yaml similarity index 100% rename from Documentation/devicetree/bindings/iio/adc/aspeed,ast2400-adc.yaml rename to Documentation/devicetree/bindings/iio/adc/aspeed,adc.yaml From patchwork Mon Jul 19 08:06:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Billy Tsai X-Patchwork-Id: 480166 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=-16.8 required=3.0 tests=BAYES_00, 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 7E111C636C9 for ; Mon, 19 Jul 2021 08:05:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6A2BC61164 for ; Mon, 19 Jul 2021 08:05:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235226AbhGSII4 (ORCPT ); Mon, 19 Jul 2021 04:08:56 -0400 Received: from twspam01.aspeedtech.com ([211.20.114.71]:38284 "EHLO twspam01.aspeedtech.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235115AbhGSIIy (ORCPT ); Mon, 19 Jul 2021 04:08:54 -0400 Received: from mail.aspeedtech.com ([192.168.0.24]) by twspam01.aspeedtech.com with ESMTP id 16J7nQKL015321; Mon, 19 Jul 2021 15:49:26 +0800 (GMT-8) (envelope-from billy_tsai@aspeedtech.com) Received: from BillyTsai-pc.aspeed.com (192.168.2.149) by TWMBX02.aspeed.com (192.168.0.24) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 19 Jul 2021 16:05:48 +0800 From: Billy Tsai To: , , , , , , , , , , , , CC: Subject: [v1 2/7] dt-bindings: iio: adc: Binding ast2600 adc. Date: Mon, 19 Jul 2021 16:06:02 +0800 Message-ID: <20210719080607.28712-3-billy_tsai@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210719080607.28712-1-billy_tsai@aspeedtech.com> References: <20210719080607.28712-1-billy_tsai@aspeedtech.com> MIME-Version: 1.0 X-Originating-IP: [192.168.2.149] X-ClientProxiedBy: TWMBX02.aspeed.com (192.168.0.24) To TWMBX02.aspeed.com (192.168.0.24) X-DNSRBL: X-MAIL: twspam01.aspeedtech.com 16J7nQKL015321 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch add more description about aspeed adc and add vref property for ast2600 to configure it reference voltage. Signed-off-by: Billy Tsai --- .../bindings/iio/adc/aspeed,adc.yaml | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/aspeed,adc.yaml b/Documentation/devicetree/bindings/iio/adc/aspeed,adc.yaml index 7f534a933e92..67ff0b5c7ef2 100644 --- a/Documentation/devicetree/bindings/iio/adc/aspeed,adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/aspeed,adc.yaml @@ -10,14 +10,26 @@ maintainers: - Joel Stanley description: - This device is a 10-bit converter for 16 voltage channels. All inputs are - single ended. + • 10-bits resolution for 16 voltage channels. + At ast2400/ast2500 the device has only one engine with 16 voltage channels. + At ast2600 the device split into two individual engine and each contains 8 voltage channels. + • Channel scanning can be non-continuous. + • Programmable ADC clock frequency. + • Programmable upper and lower bound for each channels. + • Interrupt when larger or less than bounds for each channels. + • Support hysteresis for each channels. + • Buildin a compensating method. + Additional feature at ast2600 + • Internal or External reference voltage. + • Support 2 Internal reference voltage 1.2v or 2.5v. + • Integrate dividing circuit for battery sensing. properties: compatible: enum: - aspeed,ast2400-adc - aspeed,ast2500-adc + - aspeed,ast2600-adc reg: maxItems: 1 @@ -33,6 +45,13 @@ properties: "#io-channel-cells": const: 1 + vref: + minItems: 900 + maxItems: 2700 + default: 2500 + description: + ADC Reference voltage in millivolts (only work at ast2600) + required: - compatible - reg From patchwork Mon Jul 19 08:06:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Billy Tsai X-Patchwork-Id: 480164 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=-13.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, 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 9412FC636C9 for ; Mon, 19 Jul 2021 08:06:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7E9CA61164 for ; Mon, 19 Jul 2021 08:06:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235018AbhGSIJS (ORCPT ); Mon, 19 Jul 2021 04:09:18 -0400 Received: from twspam01.aspeedtech.com ([211.20.114.71]:38321 "EHLO twspam01.aspeedtech.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235129AbhGSIJP (ORCPT ); Mon, 19 Jul 2021 04:09:15 -0400 Received: from mail.aspeedtech.com ([192.168.0.24]) by twspam01.aspeedtech.com with ESMTP id 16J7nRfm015323; Mon, 19 Jul 2021 15:49:27 +0800 (GMT-8) (envelope-from billy_tsai@aspeedtech.com) Received: from BillyTsai-pc.aspeed.com (192.168.2.149) by TWMBX02.aspeed.com (192.168.0.24) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 19 Jul 2021 16:05:48 +0800 From: Billy Tsai To: , , , , , , , , , , , , CC: Subject: [v1 4/7] iio: adc: aspeed: Allow driver to support ast2600 Date: Mon, 19 Jul 2021 16:06:04 +0800 Message-ID: <20210719080607.28712-5-billy_tsai@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210719080607.28712-1-billy_tsai@aspeedtech.com> References: <20210719080607.28712-1-billy_tsai@aspeedtech.com> MIME-Version: 1.0 X-Originating-IP: [192.168.2.149] X-ClientProxiedBy: TWMBX02.aspeed.com (192.168.0.24) To TWMBX02.aspeed.com (192.168.0.24) X-DNSRBL: X-MAIL: twspam01.aspeedtech.com 16J7nRfm015323 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The adc controller have some differents at ast2600: 1. Combine control register of clock divider to continuous bitfields. 2. Reference voltage becomes optional which are internal 2500mv/1200mv and external range from 900mv to 2700mv 3. Divided into two engine, each one has 8 voltage sensing channels. This patch handled these changes and compatible with old version. Signed-off-by: Billy Tsai --- drivers/iio/adc/aspeed_adc.c | 171 ++++++++++++++++++++++++++--------- 1 file changed, 127 insertions(+), 44 deletions(-) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 99466a5924c7..6a77ac4e7dcb 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Aspeed AST2400/2500 ADC + * Aspeed AST2400/2500/2600 ADC * * Copyright (C) 2017 Google, Inc. + * Copyright (C) 2021 Aspeed Technology Inc. */ #include @@ -55,12 +56,17 @@ #define ASPEED_ADC_INIT_POLLING_TIME 500 #define ASPEED_ADC_INIT_TIMEOUT 500000 +enum aspeed_adc_version { + aspeed_adc_ast2400, + aspeed_adc_ast2500, + aspeed_adc_ast2600, +}; struct aspeed_adc_model_data { - const char *model_name; + enum aspeed_adc_version version; unsigned int min_sampling_rate; // Hz unsigned int max_sampling_rate; // Hz - unsigned int vref_voltage; // mV bool wait_init_sequence; + unsigned int num_channels; }; struct aspeed_adc_data { @@ -70,6 +76,7 @@ struct aspeed_adc_data { struct clk_hw *clk_prescaler; struct clk_hw *clk_scaler; struct reset_control *rst; + int vref; }; #define ASPEED_CHAN(_idx, _data_reg_addr) { \ @@ -106,8 +113,6 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct aspeed_adc_data *data = iio_priv(indio_dev); - const struct aspeed_adc_model_data *model_data = - of_device_get_match_data(data->dev); switch (mask) { case IIO_CHAN_INFO_RAW: @@ -115,7 +120,7 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = model_data->vref_voltage; + *val = data->vref; *val2 = ASPEED_RESOLUTION_BITS; return IIO_VAL_FRACTIONAL_LOG2; @@ -182,6 +187,55 @@ static const struct iio_info aspeed_adc_iio_info = { .debugfs_reg_access = aspeed_adc_reg_access, }; +static int aspeed_adc_vref_config(struct platform_device *pdev) +{ + const struct aspeed_adc_model_data *model_data; + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct aspeed_adc_data *data = iio_priv(indio_dev); + int vref; + u32 adc_engine_control_reg_val = + readl(data->base + ASPEED_REG_ENGINE_CONTROL); + + model_data = of_device_get_match_data(&pdev->dev); + switch (model_data->version) { + case aspeed_adc_ast2400: + vref = 2500; + break; + case aspeed_adc_ast2500: + vref = 1800; + break; + case aspeed_adc_ast2600: + if (of_property_read_u32(pdev->dev.of_node, "vref", &vref)) + vref = 2500; + if (vref == 2500) + writel(adc_engine_control_reg_val | + ASPEED_ADC_REF_VOLTAGE_2500mV, + data->base + ASPEED_REG_ENGINE_CONTROL); + else if (vref == 1200) + writel(adc_engine_control_reg_val | + ASPEED_ADC_REF_VOLTAGE_1200mV, + data->base + ASPEED_REG_ENGINE_CONTROL); + else if ((vref >= 1550) && (vref <= 2700)) + writel(adc_engine_control_reg_val | + ASPEED_ADC_REF_VOLTAGE_EXT_HIGH, + data->base + ASPEED_REG_ENGINE_CONTROL); + else if ((vref >= 900) && (vref <= 1650)) + writel(adc_engine_control_reg_val | + ASPEED_ADC_REF_VOLTAGE_EXT_LOW, + data->base + ASPEED_REG_ENGINE_CONTROL); + else { + dev_err(&pdev->dev, "Vref not support"); + return -EOPNOTSUPP; + } + break; + default: + dev_err(&pdev->dev, "ADC version not recognized"); + return -EOPNOTSUPP; + } + data->vref = vref; + return 0; +} + static int aspeed_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; @@ -190,13 +244,16 @@ static int aspeed_adc_probe(struct platform_device *pdev) const char *clk_parent_name; int ret; u32 adc_engine_control_reg_val; + char scaler_clk_name[32]; + model_data = of_device_get_match_data(&pdev->dev); indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); data->dev = &pdev->dev; + dev_set_drvdata(data->dev, indio_dev); data->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->base)) @@ -205,29 +262,39 @@ static int aspeed_adc_probe(struct platform_device *pdev) /* Register ADC clock prescaler with source specified by device tree. */ spin_lock_init(&data->clk_lock); clk_parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0); + if (model_data->version <= aspeed_adc_ast2500) { + data->clk_prescaler = clk_hw_register_divider( + &pdev->dev, "prescaler", clk_parent_name, 0, + data->base + ASPEED_REG_CLOCK_CONTROL, + 17, 15, 0, &data->clk_lock); + if (IS_ERR(data->clk_prescaler)) + return PTR_ERR(data->clk_prescaler); - data->clk_prescaler = clk_hw_register_divider( - &pdev->dev, "prescaler", clk_parent_name, 0, - data->base + ASPEED_REG_CLOCK_CONTROL, - 17, 15, 0, &data->clk_lock); - if (IS_ERR(data->clk_prescaler)) - return PTR_ERR(data->clk_prescaler); - - /* - * Register ADC clock scaler downstream from the prescaler. Allow rate - * setting to adjust the prescaler as well. - */ - data->clk_scaler = clk_hw_register_divider( - &pdev->dev, "scaler", "prescaler", - CLK_SET_RATE_PARENT, - data->base + ASPEED_REG_CLOCK_CONTROL, - 0, 10, 0, &data->clk_lock); - if (IS_ERR(data->clk_scaler)) { - ret = PTR_ERR(data->clk_scaler); - goto scaler_error; + /* + * Register ADC clock scaler downstream from the prescaler. Allow rate + * setting to adjust the prescaler as well. + */ + data->clk_scaler = clk_hw_register_divider( + &pdev->dev, "scaler", "prescaler", + CLK_SET_RATE_PARENT, + data->base + ASPEED_REG_CLOCK_CONTROL, + 0, 10, 0, &data->clk_lock); + if (IS_ERR(data->clk_scaler)) { + ret = PTR_ERR(data->clk_scaler); + goto scaler_error; + } + } else { + snprintf(scaler_clk_name, sizeof(scaler_clk_name), "scaler-%s", + pdev->name); + data->clk_scaler = clk_hw_register_divider( + &pdev->dev, scaler_clk_name, clk_parent_name, 0, + data->base + ASPEED_REG_CLOCK_CONTROL, 0, 16, 0, + &data->clk_lock); + if (IS_ERR(data->clk_scaler)) + return PTR_ERR(data->clk_scaler); } - data->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); + data->rst = devm_reset_control_get_shared(&pdev->dev, NULL); if (IS_ERR(data->rst)) { dev_err(&pdev->dev, "invalid or missing reset controller device tree entry"); @@ -236,8 +303,6 @@ static int aspeed_adc_probe(struct platform_device *pdev) } reset_control_deassert(data->rst); - model_data = of_device_get_match_data(&pdev->dev); - if (model_data->wait_init_sequence) { /* Enable engine in normal mode. */ writel(ASPEED_ADC_OPERATION_MODE_NORMAL | ASPEED_ADC_ENGINE_ENABLE, @@ -254,22 +319,26 @@ static int aspeed_adc_probe(struct platform_device *pdev) goto poll_timeout_error; } - /* Start all channels in normal mode. */ + ret = aspeed_adc_vref_config(pdev); + if (ret) + goto vref_config_error; ret = clk_prepare_enable(data->clk_scaler->clk); if (ret) goto clk_enable_error; - - adc_engine_control_reg_val = GENMASK(31, 16) | - ASPEED_ADC_OPERATION_MODE_NORMAL | ASPEED_ADC_ENGINE_ENABLE; + adc_engine_control_reg_val = + readl(data->base + ASPEED_REG_ENGINE_CONTROL); + /* Start all channels in normal mode. */ + adc_engine_control_reg_val |= ASPEED_ADC_CTRL_CHANNEL | + ASPEED_ADC_OPERATION_MODE_NORMAL | + ASPEED_ADC_ENGINE_ENABLE; writel(adc_engine_control_reg_val, data->base + ASPEED_REG_ENGINE_CONTROL); - model_data = of_device_get_match_data(&pdev->dev); - indio_dev->name = model_data->model_name; + indio_dev->name = dev_name(&pdev->dev); indio_dev->info = &aspeed_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = aspeed_adc_iio_channels; - indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels); + indio_dev->num_channels = model_data->num_channels; ret = iio_device_register(indio_dev); if (ret) @@ -281,13 +350,15 @@ static int aspeed_adc_probe(struct platform_device *pdev) writel(ASPEED_ADC_OPERATION_MODE_POWER_DOWN, data->base + ASPEED_REG_ENGINE_CONTROL); clk_disable_unprepare(data->clk_scaler->clk); +vref_config_error: clk_enable_error: poll_timeout_error: reset_control_assert(data->rst); reset_error: clk_hw_unregister_divider(data->clk_scaler); scaler_error: - clk_hw_unregister_divider(data->clk_prescaler); + if (model_data->version <= aspeed_adc_ast2500) + clk_hw_unregister_divider(data->clk_prescaler); return ret; } @@ -295,36 +366,48 @@ static int aspeed_adc_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct aspeed_adc_data *data = iio_priv(indio_dev); + const struct aspeed_adc_model_data *model_data; + model_data = of_device_get_match_data(&pdev->dev); iio_device_unregister(indio_dev); writel(ASPEED_ADC_OPERATION_MODE_POWER_DOWN, data->base + ASPEED_REG_ENGINE_CONTROL); clk_disable_unprepare(data->clk_scaler->clk); reset_control_assert(data->rst); clk_hw_unregister_divider(data->clk_scaler); - clk_hw_unregister_divider(data->clk_prescaler); + if (model_data->version <= aspeed_adc_ast2500) + clk_hw_unregister_divider(data->clk_prescaler); return 0; } static const struct aspeed_adc_model_data ast2400_model_data = { - .model_name = "ast2400-adc", - .vref_voltage = 2500, // mV + .version = aspeed_adc_ast2400, .min_sampling_rate = 10000, .max_sampling_rate = 500000, + .num_channels = 16, }; static const struct aspeed_adc_model_data ast2500_model_data = { - .model_name = "ast2500-adc", - .vref_voltage = 1800, // mV - .min_sampling_rate = 1, - .max_sampling_rate = 1000000, + .version = aspeed_adc_ast2500, + .min_sampling_rate = 10000, + .max_sampling_rate = 500000, + .wait_init_sequence = true, + .num_channels = 16, +}; + +static const struct aspeed_adc_model_data ast2600_model_data = { + .version = aspeed_adc_ast2600, + .min_sampling_rate = 10000, + .max_sampling_rate = 500000, .wait_init_sequence = true, + .num_channels = 8, }; static const struct of_device_id aspeed_adc_matches[] = { { .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data }, { .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data }, + { .compatible = "aspeed,ast2600-adc", .data = &ast2600_model_data }, {}, }; MODULE_DEVICE_TABLE(of, aspeed_adc_matches); @@ -341,5 +424,5 @@ static struct platform_driver aspeed_adc_driver = { module_platform_driver(aspeed_adc_driver); MODULE_AUTHOR("Rick Altherr "); -MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver"); +MODULE_DESCRIPTION("Aspeed AST2400/2500/2600 ADC Driver"); MODULE_LICENSE("GPL"); From patchwork Mon Jul 19 08:06:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Billy Tsai X-Patchwork-Id: 480163 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=-16.8 required=3.0 tests=BAYES_00, 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 9B55EC12002 for ; Mon, 19 Jul 2021 08:06:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7DA50611BF for ; Mon, 19 Jul 2021 08:06:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234933AbhGSIJ1 (ORCPT ); Mon, 19 Jul 2021 04:09:27 -0400 Received: from twspam01.aspeedtech.com ([211.20.114.71]:38350 "EHLO twspam01.aspeedtech.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235154AbhGSIJZ (ORCPT ); Mon, 19 Jul 2021 04:09:25 -0400 Received: from mail.aspeedtech.com ([192.168.0.24]) by twspam01.aspeedtech.com with ESMTP id 16J7nRHu015325; Mon, 19 Jul 2021 15:49:27 +0800 (GMT-8) (envelope-from billy_tsai@aspeedtech.com) Received: from BillyTsai-pc.aspeed.com (192.168.2.149) by TWMBX02.aspeed.com (192.168.0.24) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 19 Jul 2021 16:05:49 +0800 From: Billy Tsai To: , , , , , , , , , , , , CC: Subject: [v1 6/7] iio: adc: aspeed: Add compensation phase. Date: Mon, 19 Jul 2021 16:06:06 +0800 Message-ID: <20210719080607.28712-7-billy_tsai@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210719080607.28712-1-billy_tsai@aspeedtech.com> References: <20210719080607.28712-1-billy_tsai@aspeedtech.com> MIME-Version: 1.0 X-Originating-IP: [192.168.2.149] X-ClientProxiedBy: TWMBX02.aspeed.com (192.168.0.24) To TWMBX02.aspeed.com (192.168.0.24) X-DNSRBL: X-MAIL: twspam01.aspeedtech.com 16J7nRHu015325 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds a compensation phase to improve the accurate of adc measurement. This is the builtin function though input half of the reference voltage to get the adc offset. Signed-off-by: Billy Tsai --- drivers/iio/adc/aspeed_adc.c | 51 +++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index b33ff9f0a3af..b0d7a58cb7f5 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -56,6 +56,7 @@ #define ASPEED_ADC_INIT_POLLING_TIME 500 #define ASPEED_ADC_INIT_TIMEOUT 500000 #define ASPEED_ADC_DEF_SAMPLING_RATE 250000 +#define ASPEED_ADC_MAX_RAW_DATA GENMASK(9, 0) enum aspeed_adc_version { aspeed_adc_ast2400, @@ -79,6 +80,7 @@ struct aspeed_adc_data { struct reset_control *rst; int vref; u32 sample_period_ns; + int cv; }; #define ASPEED_CHAN(_idx, _data_reg_addr) { \ @@ -110,6 +112,48 @@ static const struct iio_chan_spec aspeed_adc_iio_channels[] = { ASPEED_CHAN(15, 0x2E), }; +static int aspeed_adc_compensation(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct aspeed_adc_data *data = iio_priv(indio_dev); + u32 index, adc_raw = 0; + u32 adc_engine_control_reg_val = + readl(data->base + ASPEED_REG_ENGINE_CONTROL); + adc_engine_control_reg_val |= + (ASPEED_ADC_OPERATION_MODE_NORMAL | ASPEED_ADC_ENGINE_ENABLE); + + /* + * Enable compensating sensing: + * After that, the input voltage of adc will force to half of the reference + * voltage. So the expected reading raw data will become half of the max + * value. We can get compensating value = 0x200 - adc read raw value. + * It is recommended to average at least 10 samples to get a final CV. + */ + writel(adc_engine_control_reg_val | ASPEED_ADC_CTRL_COMPENSATION | + ASPEED_ADC_CTRL_CHANNEL_ENABLE(0), + data->base + ASPEED_REG_ENGINE_CONTROL); + /* + * After enable compensating sensing mode need to wait some time for adc stable + * Experiment result is 1ms. + */ + mdelay(1); + + for (index = 0; index < 16; index++) { + /* + * Waiting for the sampling period ensures that the value acquired + * is fresh each time. + */ + ndelay(data->sample_period_ns); + adc_raw += readw(data->base + aspeed_adc_iio_channels[0].address); + } + adc_raw >>= 4; + data->cv = BIT(ASPEED_RESOLUTION_BITS - 1) - adc_raw; + writel(adc_engine_control_reg_val, + data->base + ASPEED_REG_ENGINE_CONTROL); + dev_dbg(data->dev, "compensating value = %d\n", data->cv); + return 0; +} + static int aspeed_adc_set_sampling_rate(struct iio_dev *indio_dev, u32 rate) { struct aspeed_adc_data *data = iio_priv(indio_dev); @@ -138,7 +182,11 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - *val = readw(data->base + chan->address); + *val = readw(data->base + chan->address) + data->cv; + if (*val < 0) + *val = 0; + else if (*val >= ASPEED_ADC_MAX_RAW_DATA) + *val = ASPEED_ADC_MAX_RAW_DATA; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -338,6 +386,7 @@ static int aspeed_adc_probe(struct platform_device *pdev) if (ret) goto clk_enable_error; aspeed_adc_set_sampling_rate(indio_dev, ASPEED_ADC_DEF_SAMPLING_RATE); + aspeed_adc_compensation(pdev); adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL); /* Start all channels in normal mode. */