From patchwork Mon May 13 14:53:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Michaelis X-Patchwork-Id: 10941171 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 65E44933 for ; Mon, 13 May 2019 14:53:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 57A4327FB7 for ; Mon, 13 May 2019 14:53:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4B54328346; Mon, 13 May 2019 14:53:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CFCBF27FB7 for ; Mon, 13 May 2019 14:53:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730956AbfEMOxw (ORCPT ); Mon, 13 May 2019 10:53:52 -0400 Received: from ch3vs01.rockwellcollins.com ([205.175.226.27]:63586 "EHLO ch3vs01.rockwellcollins.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730696AbfEMOxw (ORCPT ); Mon, 13 May 2019 10:53:52 -0400 Received: from ofwch3n02.rockwellcollins.com (HELO ciulimr01.rockwellcollins.com) ([205.175.226.14]) by ch3vs01.rockwellcollins.com with ESMTP; 13 May 2019 09:53:51 -0500 X-Received: from righttwix.rockwellcollins.com (righttwix.rockwellcollins.com [192.168.141.218]) by ciulimr01.rockwellcollins.com (Postfix) with ESMTP id 0C6FE601D0; Mon, 13 May 2019 09:53:51 -0500 (CDT) From: Adam Michaelis To: linux-iio@vger.kernel.org Cc: lars@metafoo.de, michael.hennerich@analog.com, jic23@kernel.org, knaack.h@gmx.de, pmeerw@pmeerw.net, robh+dt@kernel.org, mark.rutland@arm.com, charles-antoine.couret@essensium.com, devicetree@vger.kernel.org, brandon.maier@rockwellcollins.com, clayton.shotwell@rockwellcollins.com, Adam Michaelis Subject: [PATCH v3 1/5] iio: ad7949: Fix dummy read cycle placement Date: Mon, 13 May 2019 09:53:01 -0500 Message-Id: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> X-Mailer: git-send-email 1.9.1 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The AD7949 requires two conversion cycles following the first configuration change, and one extra cycle following any other configuration change (including changing the analog channel being sampled). Therefore, adding a dummy read cycle when config is changed and removing the extra cycle at initial configuration (the first dummy cycle is now performed as part of applying the configuration change). Signed-off-by: Adam Michaelis --- V2: - Add some defines to reduce use of magic numbers. V3: - Switch back to using a u32 data buffer. - Add-back the second dummy cycle on initialization. - Move to first patch in series. --- drivers/iio/adc/ad7949.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index ac0ffff6c5ae..c7fe27aa2519 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -100,6 +100,23 @@ static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val, * send a new command to the device */ udelay(2); + + /* + * Perform extra read cycle to allow configuration, acquisition, + * and conversion sequences to complete for new configuration. + */ + ad7949_adc->buffer = 0; + + spi_message_init_with_transfers(&msg, tx, 1); + + ret = spi_sync(ad7949_adc->spi, &msg); + + /* + * This delay is to avoid a new request before the required time + * to send a new command to the device. + */ + udelay(2); + return ret; } @@ -229,11 +246,10 @@ static int ad7949_spi_init(struct ad7949_adc_chip *ad7949_adc) ret = ad7949_spi_write_cfg(ad7949_adc, 0x3C79, AD7949_MASK_TOTAL); /* - * Do two dummy conversions to apply the first configuration setting. + * Do a dummy conversion to apply the first configuration setting. * Required only after the start up of the device. */ ad7949_spi_read_channel(ad7949_adc, &val, ad7949_adc->current_channel); - ad7949_spi_read_channel(ad7949_adc, &val, ad7949_adc->current_channel); return ret; } From patchwork Mon May 13 14:53:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Michaelis X-Patchwork-Id: 10941177 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1737B933 for ; Mon, 13 May 2019 14:53:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 09BBC27FB7 for ; Mon, 13 May 2019 14:53:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F24382834A; Mon, 13 May 2019 14:53:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4D76027FB7 for ; Mon, 13 May 2019 14:53:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730961AbfEMOxx (ORCPT ); Mon, 13 May 2019 10:53:53 -0400 Received: from da1vs02.rockwellcollins.com ([205.175.227.29]:9882 "EHLO da1vs02.rockwellcollins.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730954AbfEMOxx (ORCPT ); Mon, 13 May 2019 10:53:53 -0400 Received: from ofwda1n02.rockwellcollins.com (HELO ciulimr01.rockwellcollins.com) ([205.175.227.14]) by da1vs02.rockwellcollins.com with ESMTP; 13 May 2019 09:53:51 -0500 X-Received: from righttwix.rockwellcollins.com (righttwix.rockwellcollins.com [192.168.141.218]) by ciulimr01.rockwellcollins.com (Postfix) with ESMTP id 3B09460112; Mon, 13 May 2019 09:53:51 -0500 (CDT) From: Adam Michaelis To: linux-iio@vger.kernel.org Cc: lars@metafoo.de, michael.hennerich@analog.com, jic23@kernel.org, knaack.h@gmx.de, pmeerw@pmeerw.net, robh+dt@kernel.org, mark.rutland@arm.com, charles-antoine.couret@essensium.com, devicetree@vger.kernel.org, brandon.maier@rockwellcollins.com, clayton.shotwell@rockwellcollins.com, Adam Michaelis Subject: [PATCH v3 2/5] iio: ad7949: Support internal Vref Date: Mon, 13 May 2019 09:53:02 -0500 Message-Id: <1557759185-167857-2-git-send-email-adam.michaelis@rockwellcollins.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> References: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adding configurable (via device tree) options to select one of the two external reference voltages (REFIN as default, original implementation) or one of the two internal reference voltages provided by the AD7949 part family. Signed-off-by: Adam Michaelis Acked-by: Jonathan Cameron --- V2: - Add some defines to reduce use of magic numbers. V3: - Add bitfield.h macros throughout. - Re-think usage of device tree parameter to focus on the actual reference sources instead of the raw hardware configuration. --- drivers/iio/adc/ad7949.c | 138 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 27 deletions(-) diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index c7fe27aa2519..b648b1ab9559 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -11,12 +11,23 @@ #include #include #include - -#define AD7949_MASK_CHANNEL_SEL GENMASK(9, 7) -#define AD7949_MASK_TOTAL GENMASK(13, 0) -#define AD7949_OFFSET_CHANNEL_SEL 7 -#define AD7949_CFG_READ_BACK 0x1 -#define AD7949_CFG_REG_SIZE_BITS 14 +#include +#include + +#define AD7949_CFG_REG_SIZE_BITS 14 +#define AD7949_CFG_MASK_TOTAL GENMASK(13, 0) +#define AD7949_CFG_APPLY BIT(13) +#define AD7949_CFG_CHAN_CFG GENMASK(12, 10) +#define AD7949_CFG_CHAN_CFG_UNIPOLAR_GND 0x7 +#define AD7949_CFG_CHAN_SEL GENMASK(9, 7) +#define AD7949_CFG_BW BIT(6) +#define AD7949_CFG_BW_FULL 1 +#define AD7949_CFG_REF_SEL GENMASK(5, 3) +#define AD7949_CFG_SEQ GENMASK(2, 1) +#define AD7949_CFG_SEQ_DISABLED 0x0 +#define AD7949_CFG_READBACK BIT(0) +#define AD7949_CFG_READBACK_EN 0 +#define AD7949_CFG_READBACK_DIS 1 enum { ID_AD7949 = 0, @@ -24,6 +35,18 @@ enum { ID_AD7689, }; +enum ad7949_ref_sel { + AD7949_REF_2V5 = 0, /* 2.5V internal ref + temp sensor */ + AD7949_REF_4V0, /* 4.096V internal ref + temp sensor */ + AD7949_REF_EXT_TEMP, /* REF + temp sensor */ + AD7949_REF_EXT_TEMP_BUF, /* REFIN + temp sensor */ + AD7949_REF_RSRV_4, + AD7949_REF_RSRV_5, + AD7949_REF_EXT, /* REF, no temp */ + AD7949_REF_EXT_BUF, /* REFIN, no temp */ + AD7949_REF_MAX, +}; + struct ad7949_adc_spec { u8 num_channels; u8 resolution; @@ -41,6 +64,7 @@ struct ad7949_adc_spec { * @vref: regulator generating Vref * @iio_dev: reference to iio structure * @spi: reference to spi structure + * @ref_sel: selected reference voltage source * @resolution: resolution of the chip * @cfg: copy of the configuration register * @current_channel: current channel in use @@ -51,6 +75,7 @@ struct ad7949_adc_chip { struct regulator *vref; struct iio_dev *indio_dev; struct spi_device *spi; + enum ad7949_ref_sel ref_sel; u8 resolution; u16 cfg; unsigned int current_channel; @@ -59,7 +84,7 @@ struct ad7949_adc_chip { static bool ad7949_spi_cfg_is_read_back(struct ad7949_adc_chip *ad7949_adc) { - if (!(ad7949_adc->cfg & AD7949_CFG_READ_BACK)) + if (!(ad7949_adc->cfg & AD7949_CFG_READBACK)) return true; return false; @@ -91,7 +116,7 @@ static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val, }; ad7949_adc->cfg = (val & mask) | (ad7949_adc->cfg & ~mask); - ad7949_adc->buffer = ad7949_adc->cfg << shift; + ad7949_adc->buffer = (ad7949_adc->cfg & AD7949_CFG_MASK_TOTAL) << shift; spi_message_init_with_transfers(&msg, tx, 1); ret = spi_sync(ad7949_adc->spi, &msg); @@ -136,8 +161,8 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val, }; ret = ad7949_spi_write_cfg(ad7949_adc, - channel << AD7949_OFFSET_CHANNEL_SEL, - AD7949_MASK_CHANNEL_SEL); + FIELD_PREP(AD7949_CFG_CHAN_SEL, channel), + AD7949_CFG_CHAN_SEL); if (ret) return ret; @@ -204,11 +229,20 @@ static int ad7949_spi_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret = regulator_get_voltage(ad7949_adc->vref); - if (ret < 0) - return ret; + if (ad7949_adc->vref) { + ret = regulator_get_voltage(ad7949_adc->vref); + if (ret < 0) + return ret; + + *val = ret / 5000; + } else if (ad7949_adc->ref_sel == AD7949_REF_2V5) { + *val = 2500; + } else if (ad7949_adc->ref_sel == AD7949_REF_4V0) { + *val = 4096; + } else { + return -EINVAL; + } - *val = ret / 5000; return IIO_VAL_INT; } @@ -226,7 +260,8 @@ static int ad7949_spi_reg_access(struct iio_dev *indio_dev, *readval = ad7949_adc->cfg; else ret = ad7949_spi_write_cfg(ad7949_adc, - writeval & AD7949_MASK_TOTAL, AD7949_MASK_TOTAL); + writeval & AD7949_CFG_MASK_TOTAL, + AD7949_CFG_MASK_TOTAL); return ret; } @@ -240,10 +275,24 @@ static int ad7949_spi_init(struct ad7949_adc_chip *ad7949_adc) { int ret; int val; + u16 adc_config = 0; - /* Sequencer disabled, CFG readback disabled, IN0 as default channel */ ad7949_adc->current_channel = 0; - ret = ad7949_spi_write_cfg(ad7949_adc, 0x3C79, AD7949_MASK_TOTAL); + ad7949_adc->cfg = 0; + + adc_config |= FIELD_PREP(AD7949_CFG_APPLY, 1); + adc_config |= FIELD_PREP(AD7949_CFG_CHAN_CFG, + AD7949_CFG_CHAN_CFG_UNIPOLAR_GND); + adc_config |= FIELD_PREP(AD7949_CFG_CHAN_SEL, + ad7949_adc->current_channel); + adc_config |= FIELD_PREP(AD7949_CFG_BW, AD7949_CFG_BW_FULL); + adc_config |= FIELD_PREP(AD7949_CFG_REF_SEL, ad7949_adc->ref_sel); + adc_config |= FIELD_PREP(AD7949_CFG_SEQ, AD7949_CFG_SEQ_DISABLED); + adc_config |= FIELD_PREP(AD7949_CFG_READBACK, AD7949_CFG_READBACK_DIS); + + ret = ad7949_spi_write_cfg(ad7949_adc, + adc_config, + AD7949_CFG_MASK_TOTAL); /* * Do a dummy conversion to apply the first configuration setting. @@ -261,6 +310,7 @@ static int ad7949_spi_probe(struct spi_device *spi) struct ad7949_adc_chip *ad7949_adc; struct iio_dev *indio_dev; int ret; + u32 temp; indio_dev = devm_iio_device_alloc(dev, sizeof(*ad7949_adc)); if (!indio_dev) { @@ -279,21 +329,53 @@ static int ad7949_spi_probe(struct spi_device *spi) ad7949_adc = iio_priv(indio_dev); ad7949_adc->indio_dev = indio_dev; ad7949_adc->spi = spi; + ad7949_adc->vref = NULL; spec = &ad7949_adc_spec[spi_get_device_id(spi)->driver_data]; indio_dev->num_channels = spec->num_channels; ad7949_adc->resolution = spec->resolution; - ad7949_adc->vref = devm_regulator_get(dev, "vref"); - if (IS_ERR(ad7949_adc->vref)) { - dev_err(dev, "fail to request regulator\n"); - return PTR_ERR(ad7949_adc->vref); + ret = of_property_read_u32(ad7949_adc->indio_dev->dev.of_node, + "adi,reference-select", + &temp); + if (ret == 0) { + switch (temp) { + case 0: + ad7949_adc->ref_sel = AD7949_REF_2V5; + break; + case 1: + ad7949_adc->ref_sel = AD7949_REF_4V0; + break; + case 2: + ad7949_adc->ref_sel = AD7949_REF_EXT; + break; + case 3: + ad7949_adc->ref_sel = AD7949_REF_EXT_BUF; + break; + default: + ad7949_adc->ref_sel = AD7949_REF_EXT_BUF; + dev_warn(dev, + "unknown reference-select value, using REFIN external Vref (3) by default\n"); + } + } else { + ad7949_adc->ref_sel = AD7949_REF_EXT_BUF; + dev_warn(dev, "using external Vref by default\n"); } - ret = regulator_enable(ad7949_adc->vref); - if (ret < 0) { - dev_err(dev, "fail to enable regulator\n"); - return ret; + /* Check whether using external Vref */ + if ((ad7949_adc->ref_sel != AD7949_REF_2V5) && + (ad7949_adc->ref_sel != AD7949_REF_4V0)) { + ad7949_adc->vref = devm_regulator_get(dev, "vref"); + if (IS_ERR(ad7949_adc->vref)) { + dev_err(dev, "fail to request regulator\n"); + return PTR_ERR(ad7949_adc->vref); + } + + ret = regulator_enable(ad7949_adc->vref); + if (ret < 0) { + dev_err(dev, "fail to enable regulator\n"); + return ret; + } } mutex_init(&ad7949_adc->lock); @@ -314,7 +396,8 @@ static int ad7949_spi_probe(struct spi_device *spi) err: mutex_destroy(&ad7949_adc->lock); - regulator_disable(ad7949_adc->vref); + if (ad7949_adc->vref) + regulator_disable(ad7949_adc->vref); return ret; } @@ -326,7 +409,8 @@ static int ad7949_spi_remove(struct spi_device *spi) iio_device_unregister(indio_dev); mutex_destroy(&ad7949_adc->lock); - regulator_disable(ad7949_adc->vref); + if (ad7949_adc->vref) + regulator_disable(ad7949_adc->vref); return 0; } From patchwork Mon May 13 14:53:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Michaelis X-Patchwork-Id: 10941173 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AEF441395 for ; Mon, 13 May 2019 14:53:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A203C27FB7 for ; Mon, 13 May 2019 14:53:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9624B2833E; Mon, 13 May 2019 14:53:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3968627FB7 for ; Mon, 13 May 2019 14:53:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730954AbfEMOxx (ORCPT ); Mon, 13 May 2019 10:53:53 -0400 Received: from ch3vs01.rockwellcollins.com ([205.175.226.27]:63586 "EHLO ch3vs01.rockwellcollins.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730955AbfEMOxx (ORCPT ); Mon, 13 May 2019 10:53:53 -0400 Received: from ofwch3n02.rockwellcollins.com (HELO ciulimr01.rockwellcollins.com) ([205.175.226.14]) by ch3vs01.rockwellcollins.com with ESMTP; 13 May 2019 09:53:51 -0500 X-Received: from righttwix.rockwellcollins.com (righttwix.rockwellcollins.com [192.168.141.218]) by ciulimr01.rockwellcollins.com (Postfix) with ESMTP id A980160185; Mon, 13 May 2019 09:53:51 -0500 (CDT) From: Adam Michaelis To: linux-iio@vger.kernel.org Cc: lars@metafoo.de, michael.hennerich@analog.com, jic23@kernel.org, knaack.h@gmx.de, pmeerw@pmeerw.net, robh+dt@kernel.org, mark.rutland@arm.com, charles-antoine.couret@essensium.com, devicetree@vger.kernel.org, brandon.maier@rockwellcollins.com, clayton.shotwell@rockwellcollins.com, Adam Michaelis Subject: [PATCH v3 3/5] dt-bindings: iio: ad7949: Add adi,reference-select Date: Mon, 13 May 2019 09:53:03 -0500 Message-Id: <1557759185-167857-3-git-send-email-adam.michaelis@rockwellcollins.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> References: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adding optional parameter to AD7949 to specify the source for the reference voltage signal. Default value is maintained with option '3' to match previous version of driver. Signed-off-by: Adam Michaelis Reviewed-by: Rob Herring Acked-by: Jonathan Cameron Acked-by: Alexandru Ardelean --- V2: - Add some defines to reduce use of magic numbers. V3: - Re-think usage of device tree parameter to focus on the actual reference sources instead of the raw hardware configuration. --- .../devicetree/bindings/iio/adc/ad7949.txt | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/ad7949.txt b/Documentation/devicetree/bindings/iio/adc/ad7949.txt index c7f5057356b1..e5152335c761 100644 --- a/Documentation/devicetree/bindings/iio/adc/ad7949.txt +++ b/Documentation/devicetree/bindings/iio/adc/ad7949.txt @@ -6,11 +6,28 @@ Required properties: * "adi,ad7682" * "adi,ad7689" - reg: spi chip select number for the device - - vref-supply: The regulator supply for ADC reference voltage -Example: +Optional properties: + - adi,reference-select: Select the reference voltage source to use + when converting the input voltages. Valid values are: + 0: Internal 2.5V reference; + 1: Internal 4.096V reference; + 2: External REF reference; + 3: External REFIN reference (default); + - vref-supply: The regulator supply for external ADC reference voltage. + Required if one of the external references is selected by + 'adi,reference-select'. + +Examples: adc@0 { compatible = "adi,ad7949"; reg = <0>; + adi,reference-select = <2>; vref-supply = <&vdd_supply>; }; + +adc@0 { + compatible = "adi,ad7949"; + reg = <0>; + adi,reference-select = <0>; +}; From patchwork Mon May 13 14:53:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Michaelis X-Patchwork-Id: 10941179 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 60B991398 for ; Mon, 13 May 2019 14:53:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5304C27FB7 for ; Mon, 13 May 2019 14:53:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 475B22833E; Mon, 13 May 2019 14:53:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B527728068 for ; Mon, 13 May 2019 14:53:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730959AbfEMOxx (ORCPT ); Mon, 13 May 2019 10:53:53 -0400 Received: from ch3vs02.rockwellcollins.com ([205.175.226.29]:24836 "EHLO ch3vs02.rockwellcollins.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730958AbfEMOxw (ORCPT ); Mon, 13 May 2019 10:53:52 -0400 Received: from ofwch3n02.rockwellcollins.com (HELO ciulimr01.rockwellcollins.com) ([205.175.226.14]) by ch3vs02.rockwellcollins.com with ESMTP; 13 May 2019 09:53:52 -0500 X-Received: from righttwix.rockwellcollins.com (righttwix.rockwellcollins.com [192.168.141.218]) by ciulimr01.rockwellcollins.com (Postfix) with ESMTP id 10189600E4; Mon, 13 May 2019 09:53:52 -0500 (CDT) From: Adam Michaelis To: linux-iio@vger.kernel.org Cc: lars@metafoo.de, michael.hennerich@analog.com, jic23@kernel.org, knaack.h@gmx.de, pmeerw@pmeerw.net, robh+dt@kernel.org, mark.rutland@arm.com, charles-antoine.couret@essensium.com, devicetree@vger.kernel.org, brandon.maier@rockwellcollins.com, clayton.shotwell@rockwellcollins.com, Adam Michaelis Subject: [PATCH v3 4/5] iio: ad7949: Fix SPI interfacing for 14-bit messages Date: Mon, 13 May 2019 09:53:04 -0500 Message-Id: <1557759185-167857-4-git-send-email-adam.michaelis@rockwellcollins.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> References: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The AD7949 (but not the other two models supported by this driver) uses samples 14 bits wide. When attempting to communicate through certain SPI controllers that do not support word widths of 14, this fails. Adding logic to pack the 14-bit messages into the most-significant bits of a 16-bit message or a 2-word 8-bit message for communication using more SPI bus controllers. Only able to test with AD7949 part on Cadence SPI, but should support the 16-bit samples of the AD7682 and AD7689, as well. Signed-off-by: Adam Michaelis Acked-by: Jonathan Cameron --- V2: - Add some defines to reduce use of magic numbers. V3: - Use union for message buffer to keep messages word-aligned for various word sizes. - Calculate SPI bits-per-word once and use for logic throughout. - Add logic to use SPI controller's bits-per-word field to make the most use of the hardware's capabilities. - Try to support SPI word widths of 16, 14, and 8 bits. --- drivers/iio/adc/ad7949.c | 115 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 28 deletions(-) diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index b648b1ab9559..d67033a008e5 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -78,10 +78,30 @@ struct ad7949_adc_chip { enum ad7949_ref_sel ref_sel; u8 resolution; u16 cfg; + u8 bits_per_word; unsigned int current_channel; - u32 buffer ____cacheline_aligned; + union { + u32 buffer; + u16 buf16[2]; + u8 buf8[4]; + } ____cacheline_aligned; }; +static void ad7949_set_bits_per_word(struct ad7949_adc_chip *ad7949_adc) +{ + /* Prefer messages that match the ADC's resolution */ + if (ad7949_adc->spi->controller->bits_per_word_mask & + SPI_BPW_MASK(ad7949_adc->resolution)) + ad7949_adc->bits_per_word = ad7949_adc->resolution; + /* Second choice is to pad 14-bit words to 16 */ + else if (ad7949_adc->spi->controller->bits_per_word_mask & + SPI_BPW_MASK(16)) + ad7949_adc->bits_per_word = 16; + /* Last resort, use 8-bit words */ + else + ad7949_adc->bits_per_word = 8; +} + static bool ad7949_spi_cfg_is_read_back(struct ad7949_adc_chip *ad7949_adc) { if (!(ad7949_adc->cfg & AD7949_CFG_READBACK)) @@ -90,39 +110,63 @@ static bool ad7949_spi_cfg_is_read_back(struct ad7949_adc_chip *ad7949_adc) return false; } -static int ad7949_spi_bits_per_word(struct ad7949_adc_chip *ad7949_adc) +static int ad7949_message_len(struct ad7949_adc_chip *ad7949_adc) { - int ret = ad7949_adc->resolution; + int tx_len = 2; if (ad7949_spi_cfg_is_read_back(ad7949_adc)) - ret += AD7949_CFG_REG_SIZE_BITS; + tx_len += 2; - return ret; + return tx_len; } static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val, u16 mask) { - int ret; - int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc); - int shift = bits_per_word - AD7949_CFG_REG_SIZE_BITS; + int ret = 0; + u16 tmp_cfg = 0; struct spi_message msg; struct spi_transfer tx[] = { { .tx_buf = &ad7949_adc->buffer, - .len = 4, - .bits_per_word = bits_per_word, - }, + .len = ad7949_message_len(ad7949_adc), + .bits_per_word = ad7949_adc->bits_per_word, + } }; - ad7949_adc->cfg = (val & mask) | (ad7949_adc->cfg & ~mask); - ad7949_adc->buffer = (ad7949_adc->cfg & AD7949_CFG_MASK_TOTAL) << shift; + ad7949_adc->buffer = 0; + + tmp_cfg = ((val & mask) | (ad7949_adc->cfg & ~mask)) & + AD7949_CFG_MASK_TOTAL; + + /* If no change, return */ + if (tmp_cfg == ad7949_adc->cfg) + return 0; + + ad7949_adc->cfg = tmp_cfg; + + switch (ad7949_adc->bits_per_word) { + case 16: + ad7949_adc->buf16[0] = ad7949_adc->cfg << 2; + break; + case 14: + ad7949_adc->buf16[0] = ad7949_adc->cfg; + break; + default: /* 8 */ + /* Pack 14-bit value into 2 bytes, MSB first */ + ad7949_adc->buf8[0] = FIELD_GET(GENMASK(13, 6), ad7949_adc->cfg); + ad7949_adc->buf8[1] = FIELD_GET(GENMASK(5, 0), ad7949_adc->cfg); + ad7949_adc->buf8[1] = ad7949_adc->buf8[1] << 2; + break; + } + spi_message_init_with_transfers(&msg, tx, 1); + ret = spi_sync(ad7949_adc->spi, &msg); /* - * This delay is to avoid a new request before the required time to - * send a new command to the device + * This delay is to avoid a new request before the required + * time to send a new command to the device */ udelay(2); @@ -149,17 +193,17 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val, unsigned int channel) { int ret; - int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc); - int mask = GENMASK(ad7949_adc->resolution, 0); struct spi_message msg; struct spi_transfer tx[] = { { .rx_buf = &ad7949_adc->buffer, - .len = 4, - .bits_per_word = bits_per_word, - }, + .len = ad7949_message_len(ad7949_adc), + .bits_per_word = ad7949_adc->bits_per_word, + } }; + ad7949_adc->current_channel = channel; + ret = ad7949_spi_write_cfg(ad7949_adc, FIELD_PREP(AD7949_CFG_CHAN_SEL, channel), AD7949_CFG_CHAN_SEL); @@ -167,23 +211,37 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val, return ret; ad7949_adc->buffer = 0; + spi_message_init_with_transfers(&msg, tx, 1); + ret = spi_sync(ad7949_adc->spi, &msg); if (ret) return ret; /* - * This delay is to avoid a new request before the required time to - * send a new command to the device + * This delay is to avoid a new request before the required time + * to send a new command to the device. */ udelay(2); - ad7949_adc->current_channel = channel; - - if (ad7949_spi_cfg_is_read_back(ad7949_adc)) - *val = (ad7949_adc->buffer >> AD7949_CFG_REG_SIZE_BITS) & mask; - else - *val = ad7949_adc->buffer & mask; + switch (ad7949_adc->bits_per_word) { + case 16: + *val = ad7949_adc->buf16[0]; + /* Shift-out padding bits */ + if (ad7949_adc->resolution == 14) + *val = *val >> 2; + break; + case 14: + *val = ad7949_adc->buf16[0] & GENMASK(13, 0); + break; + default: /* 8 */ + /* Convert byte array to u16, MSB first */ + *val = (ad7949_adc->buf8[0] << 8) | ad7949_adc->buf8[1]; + /* Shift-out padding bits */ + if (ad7949_adc->resolution == 14) + *val = *val >> 2; + break; + } return 0; } @@ -334,6 +392,7 @@ static int ad7949_spi_probe(struct spi_device *spi) spec = &ad7949_adc_spec[spi_get_device_id(spi)->driver_data]; indio_dev->num_channels = spec->num_channels; ad7949_adc->resolution = spec->resolution; + ad7949_set_bits_per_word(ad7949_adc); ret = of_property_read_u32(ad7949_adc->indio_dev->dev.of_node, "adi,reference-select", From patchwork Mon May 13 14:53:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Michaelis X-Patchwork-Id: 10941175 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3C4401398 for ; Mon, 13 May 2019 14:53:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2D6FF27FB7 for ; Mon, 13 May 2019 14:53:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 21F982833E; Mon, 13 May 2019 14:53:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B840827FB7 for ; Mon, 13 May 2019 14:53:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730955AbfEMOxx (ORCPT ); Mon, 13 May 2019 10:53:53 -0400 Received: from da1vs03.rockwellcollins.com ([205.175.227.47]:49607 "EHLO da1vs03.rockwellcollins.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730696AbfEMOxx (ORCPT ); Mon, 13 May 2019 10:53:53 -0400 Received: from ofwda1n02.rockwellcollins.com (HELO ciulimr01.rockwellcollins.com) ([205.175.227.14]) by da1vs03.rockwellcollins.com with ESMTP; 13 May 2019 09:53:52 -0500 X-Received: from righttwix.rockwellcollins.com (righttwix.rockwellcollins.com [192.168.141.218]) by ciulimr01.rockwellcollins.com (Postfix) with ESMTP id 3CEDF6024D; Mon, 13 May 2019 09:53:52 -0500 (CDT) From: Adam Michaelis To: linux-iio@vger.kernel.org Cc: lars@metafoo.de, michael.hennerich@analog.com, jic23@kernel.org, knaack.h@gmx.de, pmeerw@pmeerw.net, robh+dt@kernel.org, mark.rutland@arm.com, charles-antoine.couret@essensium.com, devicetree@vger.kernel.org, brandon.maier@rockwellcollins.com, clayton.shotwell@rockwellcollins.com, Adam Michaelis Subject: [PATCH v3 5/5] iio: ad7949: Remove logic for config readback Date: Mon, 13 May 2019 09:53:05 -0500 Message-Id: <1557759185-167857-5-git-send-email-adam.michaelis@rockwellcollins.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> References: <1557759185-167857-1-git-send-email-adam.michaelis@rockwellcollins.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The AD7949 has a feature to include the configuration register value used to generate the ADC sample. This feature is configurable, but do not see a good use case for it in the driver (neither did reviewing maintainers), so removing the supporting logic in order to simplify the driver. Signed-off-by: Adam Michaelis Acked-by: Jonathan Cameron --- V3: - First version of series with this patch. Maintainers agreed that this capability of the hardware is not useful and should be dropped from driver. --- drivers/iio/adc/ad7949.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index d67033a008e5..bac16a2f7850 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -102,24 +102,6 @@ static void ad7949_set_bits_per_word(struct ad7949_adc_chip *ad7949_adc) ad7949_adc->bits_per_word = 8; } -static bool ad7949_spi_cfg_is_read_back(struct ad7949_adc_chip *ad7949_adc) -{ - if (!(ad7949_adc->cfg & AD7949_CFG_READBACK)) - return true; - - return false; -} - -static int ad7949_message_len(struct ad7949_adc_chip *ad7949_adc) -{ - int tx_len = 2; - - if (ad7949_spi_cfg_is_read_back(ad7949_adc)) - tx_len += 2; - - return tx_len; -} - static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val, u16 mask) { @@ -129,7 +111,7 @@ static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val, struct spi_transfer tx[] = { { .tx_buf = &ad7949_adc->buffer, - .len = ad7949_message_len(ad7949_adc), + .len = 2, .bits_per_word = ad7949_adc->bits_per_word, } }; @@ -197,7 +179,7 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val, struct spi_transfer tx[] = { { .rx_buf = &ad7949_adc->buffer, - .len = ad7949_message_len(ad7949_adc), + .len = 2, .bits_per_word = ad7949_adc->bits_per_word, } };