From patchwork Wed Mar 6 08:55:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840615 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 E2FE6180E for ; Wed, 6 Mar 2019 08:56:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D00C32BE02 for ; Wed, 6 Mar 2019 08:56:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C445E2CC7D; Wed, 6 Mar 2019 08:56: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 72A502C03F for ; Wed, 6 Mar 2019 08:56:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729565AbfCFI4X (ORCPT ); Wed, 6 Mar 2019 03:56:23 -0500 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:58413 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729562AbfCFI4W (ORCPT ); Wed, 6 Mar 2019 03:56:22 -0500 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268p4eU001192; Wed, 6 Mar 2019 09:55:49 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2r0ju8yewp-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:49 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 585C342; Wed, 6 Mar 2019 08:55:48 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0EE9423F7; Wed, 6 Mar 2019 08:55:48 +0000 (GMT) Received: from localhost (10.75.127.46) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:47 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 1/8] iio: adc: stm32-dfsdm: make spi_master_freq more accurate Date: Wed, 6 Mar 2019 09:55:17 +0100 Message-ID: <1551862524-25098-2-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.46] X-ClientProxiedBy: SFHDAG7NODE3.st.com (10.75.127.21) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_06:,, signatures=0 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 When SPI clock isn't accurate, 'spi_master_freq' is filled in with expected frequency. Use computed value instead: - e.g. source clock / (CKOUTDIV + 1) Also, current divider may be set to value that makes CKOUT to exceed spi-max-frequency. Rather use lower value (e.g. round up divider when ckout isn't accurate). Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c index bf089f5..65b7556 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -243,13 +243,18 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev, return 0; } - priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1; + priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem); + + /* round up divider when clkout isn't accurate (e.g. !rem) */ + if (priv->spi_clk_out_div && !rem) + priv->spi_clk_out_div--; + if (!priv->spi_clk_out_div) { /* spi_clk_out_div == 0 means ckout is OFF */ dev_err(&pdev->dev, "spi-max-frequency not achievable\n"); return -EINVAL; } - priv->dfsdm.spi_master_freq = spi_freq; + priv->dfsdm.spi_master_freq = clk_freq / (priv->spi_clk_out_div + 1); if (rem) { dev_warn(&pdev->dev, "SPI clock not accurate\n"); From patchwork Wed Mar 6 08:55:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840619 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 B698C180E for ; Wed, 6 Mar 2019 08:57:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A35E92C155 for ; Wed, 6 Mar 2019 08:57:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 97F012CC7D; Wed, 6 Mar 2019 08:57:04 +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=unavailable 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 7E0262C155 for ; Wed, 6 Mar 2019 08:57:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728438AbfCFI4T (ORCPT ); Wed, 6 Mar 2019 03:56:19 -0500 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:58447 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728899AbfCFI4S (ORCPT ); Wed, 6 Mar 2019 03:56:18 -0500 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268p4Wg001186; Wed, 6 Mar 2019 09:55:50 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2r0ju8yewt-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:50 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 5AA1841; Wed, 6 Mar 2019 08:55:49 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id C53772400; Wed, 6 Mar 2019 08:55:48 +0000 (GMT) Received: from localhost (10.75.127.44) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:48 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 2/8] iio: adc: stm32-dfsdm: continuous mode depends on current mode Date: Wed, 6 Mar 2019 09:55:18 +0100 Message-ID: <1551862524-25098-3-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.44] X-ClientProxiedBy: SFHDAG5NODE1.st.com (10.75.127.13) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_06:,, signatures=0 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 DFSDM regular continuous mode usage depends on current mode (not DMA): - for single conversion, RCONT doesn't need to be set. - for buffer mode, RCONT has to be set (e.g. INDIO_BUFFER_SOFTWARE used by audio currently). This is related to filter configuration, move it to relevant routine. This is precursor patch to ease support of triggered buffer mode. Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-adc.c | 54 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index fcd4a1c..8690672 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -38,6 +38,10 @@ #define DFSDM_MAX_RES BIT(31) #define DFSDM_DATA_RES BIT(23) +/* Filter configuration */ +#define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \ + DFSDM_CR1_RSYNC_MASK) + enum sd_converter_type { DFSDM_AUDIO, DFSDM_IIO, @@ -262,11 +266,13 @@ static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0)); } -static int stm32_dfsdm_filter_configure(struct stm32_dfsdm *dfsdm, +static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, unsigned int fl_id, unsigned int ch_id) { - struct regmap *regmap = dfsdm->regmap; - struct stm32_dfsdm_filter *fl = &dfsdm->fl_list[fl_id]; + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct regmap *regmap = adc->dfsdm->regmap; + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; + u32 cr1; int ret; /* Average integrator oversampling */ @@ -287,14 +293,16 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm *dfsdm, return ret; /* No scan mode supported for the moment */ - ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_RCH_MASK, - DFSDM_CR1_RCH(ch_id)); - if (ret) - return ret; + cr1 = DFSDM_CR1_RCH(ch_id); + + /* Continuous conversions triggered by SPI clock in buffer mode */ + if (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE) + cr1 |= DFSDM_CR1_RCONT(1); - return regmap_update_bits(regmap, DFSDM_CR1(fl_id), - DFSDM_CR1_RSYNC_MASK, - DFSDM_CR1_RSYNC(fl->sync_mode)); + cr1 |= DFSDM_CR1_RSYNC(fl->sync_mode); + + return regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_CFG_MASK, + cr1); } static int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm, @@ -426,47 +434,39 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, { struct regmap *regmap = adc->dfsdm->regmap; int ret; - unsigned int dma_en = 0, cont_en = 0; + unsigned int dma_en = 0; ret = stm32_dfsdm_start_channel(adc->dfsdm, chan->channel); if (ret < 0) return ret; - ret = stm32_dfsdm_filter_configure(adc->dfsdm, adc->fl_id, - chan->channel); + ret = stm32_dfsdm_filter_configure(adc, adc->fl_id, chan->channel); if (ret < 0) goto stop_channels; if (dma) { /* Enable DMA transfer*/ dma_en = DFSDM_CR1_RDMAEN(1); - /* Enable conversion triggered by SPI clock*/ - cont_en = DFSDM_CR1_RCONT(1); } /* Enable DMA transfer*/ ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_RDMAEN_MASK, dma_en); if (ret < 0) - goto stop_channels; - - /* Enable conversion triggered by SPI clock*/ - ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RCONT_MASK, cont_en); - if (ret < 0) - goto stop_channels; + goto filter_unconfigure; ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id); if (ret < 0) - goto stop_channels; + goto stop_dma; return 0; -stop_channels: +stop_dma: regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_RDMAEN_MASK, 0); - +filter_unconfigure: regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RCONT_MASK, 0); + DFSDM_CR1_CFG_MASK, 0); +stop_channels: stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel); return ret; @@ -484,7 +484,7 @@ static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc, DFSDM_CR1_RDMAEN_MASK, 0); regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RCONT_MASK, 0); + DFSDM_CR1_CFG_MASK, 0); stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel); } From patchwork Wed Mar 6 08:55:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840617 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 DE50617E4 for ; Wed, 6 Mar 2019 08:56:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C87792BE02 for ; Wed, 6 Mar 2019 08:56:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BC7642C155; Wed, 6 Mar 2019 08:56: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 43CE92BE02 for ; Wed, 6 Mar 2019 08:56:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729261AbfCFI4y (ORCPT ); Wed, 6 Mar 2019 03:56:54 -0500 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:27460 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729561AbfCFI4X (ORCPT ); Wed, 6 Mar 2019 03:56:23 -0500 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268sqWU015101; Wed, 6 Mar 2019 09:55:50 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2qyhgaxr3b-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:50 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id AD89634; Wed, 6 Mar 2019 08:55:49 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 7FCA62407; Wed, 6 Mar 2019 08:55:49 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:48 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 3/8] iio: adc: stm32-dfsdm: move dma enable from start_conv() to start_dma() Date: Wed, 6 Mar 2019 09:55:19 +0100 Message-ID: <1551862524-25098-4-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG3NODE1.st.com (10.75.127.7) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_04:,, signatures=0 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 Move DMA enable (e.g. set RDMAEN bit) away from start_conv() that is used for both buffer and single conversions. Thus, single conv rely on interrupt, not dma. Note: take care to prepare all DMA stuff and set RDMAEN before starting filter (can be set only when DFEN=0). This is precursor patch to ease support of triggered buffer mode. Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-adc.c | 77 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 8690672..818627f 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -429,12 +429,10 @@ static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev, } static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, - const struct iio_chan_spec *chan, - bool dma) + const struct iio_chan_spec *chan) { struct regmap *regmap = adc->dfsdm->regmap; int ret; - unsigned int dma_en = 0; ret = stm32_dfsdm_start_channel(adc->dfsdm, chan->channel); if (ret < 0) @@ -444,25 +442,12 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, if (ret < 0) goto stop_channels; - if (dma) { - /* Enable DMA transfer*/ - dma_en = DFSDM_CR1_RDMAEN(1); - } - /* Enable DMA transfer*/ - ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RDMAEN_MASK, dma_en); - if (ret < 0) - goto filter_unconfigure; - ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id); if (ret < 0) - goto stop_dma; + goto filter_unconfigure; return 0; -stop_dma: - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RDMAEN_MASK, 0); filter_unconfigure: regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK, 0); @@ -479,10 +464,6 @@ static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc, stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id); - /* Clean conversion options */ - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RDMAEN_MASK, 0); - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK, 0); @@ -599,15 +580,36 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) cookie = dmaengine_submit(desc); ret = dma_submit_error(cookie); - if (ret) { - dmaengine_terminate_all(adc->dma_chan); - return ret; - } + if (ret) + goto err_stop_dma; /* Issue pending DMA requests */ dma_async_issue_pending(adc->dma_chan); + /* Enable DMA transfer*/ + ret = regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), + DFSDM_CR1_RDMAEN_MASK, DFSDM_CR1_RDMAEN_MASK); + if (ret < 0) + goto err_stop_dma; + return 0; + +err_stop_dma: + dmaengine_terminate_all(adc->dma_chan); + + return ret; +} + +static void stm32_dfsdm_adc_dma_stop(struct iio_dev *indio_dev) +{ + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); + + if (!adc->dma_chan) + return; + + regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), + DFSDM_CR1_RDMAEN_MASK, 0); + dmaengine_terminate_all(adc->dma_chan); } static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) @@ -623,24 +625,22 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) if (ret < 0) return ret; - ret = stm32_dfsdm_start_conv(adc, chan, true); + ret = stm32_dfsdm_adc_dma_start(indio_dev); if (ret) { - dev_err(&indio_dev->dev, "Can't start conversion\n"); + dev_err(&indio_dev->dev, "Can't start DMA\n"); goto stop_dfsdm; } - if (adc->dma_chan) { - ret = stm32_dfsdm_adc_dma_start(indio_dev); - if (ret) { - dev_err(&indio_dev->dev, "Can't start DMA\n"); - goto err_stop_conv; - } + ret = stm32_dfsdm_start_conv(adc, chan); + if (ret) { + dev_err(&indio_dev->dev, "Can't start conversion\n"); + goto err_stop_dma; } return 0; -err_stop_conv: - stm32_dfsdm_stop_conv(adc, chan); +err_stop_dma: + stm32_dfsdm_adc_dma_stop(indio_dev); stop_dfsdm: stm32_dfsdm_stop_dfsdm(adc->dfsdm); @@ -652,11 +652,10 @@ static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); const struct iio_chan_spec *chan = &indio_dev->channels[0]; - if (adc->dma_chan) - dmaengine_terminate_all(adc->dma_chan); - stm32_dfsdm_stop_conv(adc, chan); + stm32_dfsdm_adc_dma_stop(indio_dev); + stm32_dfsdm_stop_dfsdm(adc->dfsdm); return 0; @@ -736,7 +735,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, if (ret < 0) goto stop_dfsdm; - ret = stm32_dfsdm_start_conv(adc, chan, false); + ret = stm32_dfsdm_start_conv(adc, chan); if (ret < 0) { regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); From patchwork Wed Mar 6 08:55:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840609 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 5162E17E4 for ; Wed, 6 Mar 2019 08:56:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E0ED2BE02 for ; Wed, 6 Mar 2019 08:56:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 325A62C155; Wed, 6 Mar 2019 08:56:44 +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 CAC632C03F for ; Wed, 6 Mar 2019 08:56:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726156AbfCFI4n (ORCPT ); Wed, 6 Mar 2019 03:56:43 -0500 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:47805 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729555AbfCFI4X (ORCPT ); Wed, 6 Mar 2019 03:56:23 -0500 Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268pquq028239; Wed, 6 Mar 2019 09:55:51 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2qygfxpr7w-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:51 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 85D273D; Wed, 6 Mar 2019 08:55:50 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6540923F7; Wed, 6 Mar 2019 08:55:50 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:49 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 4/8] iio: adc: stm32-dfsdm: move dma slave config to start routine Date: Wed, 6 Mar 2019 09:55:20 +0100 Message-ID: <1551862524-25098-5-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG4NODE2.st.com (10.75.127.11) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_06:,, signatures=0 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 Move DMA slave configuration to start routine: depending on regular or injected mode is in use, DMA needs to read resp. RDATAR or JDATAR. This is precursor patch to introduce injected mode (used for scan). Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-adc.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 818627f..66e2ea0 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -556,6 +556,11 @@ static void stm32_dfsdm_audio_dma_buffer_done(void *data) static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); + struct dma_slave_config config = { + .src_addr = (dma_addr_t)adc->dfsdm->phys_base + + DFSDM_RDATAR(adc->fl_id), + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + }; struct dma_async_tx_descriptor *desc; dma_cookie_t cookie; int ret; @@ -566,6 +571,10 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__, adc->buf_sz, adc->buf_sz / 2); + ret = dmaengine_slave_config(adc->dma_chan, &config); + if (ret) + return ret; + /* Prepare a DMA cyclic transaction */ desc = dmaengine_prep_dma_cyclic(adc->dma_chan, adc->dma_buf, @@ -925,12 +934,6 @@ static void stm32_dfsdm_dma_release(struct iio_dev *indio_dev) static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - struct dma_slave_config config = { - .src_addr = (dma_addr_t)adc->dfsdm->phys_base + - DFSDM_RDATAR(adc->fl_id), - .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, - }; - int ret; adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); if (!adc->dma_chan) @@ -940,23 +943,11 @@ static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev) DFSDM_DMA_BUFFER_SIZE, &adc->dma_buf, GFP_KERNEL); if (!adc->rx_buf) { - ret = -ENOMEM; - goto err_release; + dma_release_channel(adc->dma_chan); + return -ENOMEM; } - ret = dmaengine_slave_config(adc->dma_chan, &config); - if (ret) - goto err_free; - return 0; - -err_free: - dma_free_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE, - adc->rx_buf, adc->dma_buf); -err_release: - dma_release_channel(adc->dma_chan); - - return ret; } static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, From patchwork Wed Mar 6 08:55:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840599 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 4B800180E for ; Wed, 6 Mar 2019 08:56:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 393752C155 for ; Wed, 6 Mar 2019 08:56:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2D3512C3D6; Wed, 6 Mar 2019 08:56:37 +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 D23702C155 for ; Wed, 6 Mar 2019 08:56:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729655AbfCFI43 (ORCPT ); Wed, 6 Mar 2019 03:56:29 -0500 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:56134 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729563AbfCFI4X (ORCPT ); Wed, 6 Mar 2019 03:56:23 -0500 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268q6XN022884; Wed, 6 Mar 2019 09:55:52 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2qyhkn6rcx-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:52 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 4213D34; Wed, 6 Mar 2019 08:55:51 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0FDAA23FE; Wed, 6 Mar 2019 08:55:51 +0000 (GMT) Received: from localhost (10.75.127.44) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:50 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 5/8] iio: adc: stm32-dfsdm: enable hw consumer Date: Wed, 6 Mar 2019 09:55:21 +0100 Message-ID: <1551862524-25098-6-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.44] X-ClientProxiedBy: SFHDAG7NODE1.st.com (10.75.127.19) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_05:,, signatures=0 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 Optionally enable IIO hw consumer, when provided (e.g. for DFSDM_IIO type). This is precursor patch to introduce buffer modes. Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-adc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 66e2ea0..b491424 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -630,9 +630,15 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) /* Reset adc buffer index */ adc->bufi = 0; + if (adc->hwc) { + ret = iio_hw_consumer_enable(adc->hwc); + if (ret < 0) + return ret; + } + ret = stm32_dfsdm_start_dfsdm(adc->dfsdm); if (ret < 0) - return ret; + goto err_stop_hwc; ret = stm32_dfsdm_adc_dma_start(indio_dev); if (ret) { @@ -652,6 +658,9 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) stm32_dfsdm_adc_dma_stop(indio_dev); stop_dfsdm: stm32_dfsdm_stop_dfsdm(adc->dfsdm); +err_stop_hwc: + if (adc->hwc) + iio_hw_consumer_disable(adc->hwc); return ret; } @@ -667,6 +676,9 @@ static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) stm32_dfsdm_stop_dfsdm(adc->dfsdm); + if (adc->hwc) + iio_hw_consumer_disable(adc->hwc); + return 0; } From patchwork Wed Mar 6 08:55:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840613 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 DC8CE1390 for ; Wed, 6 Mar 2019 08:56:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C40782C155 for ; Wed, 6 Mar 2019 08:56:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B6AB22C3D6; Wed, 6 Mar 2019 08:56: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 D10102BE02 for ; Wed, 6 Mar 2019 08:56:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729269AbfCFI4n (ORCPT ); Wed, 6 Mar 2019 03:56:43 -0500 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:47806 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729559AbfCFI4X (ORCPT ); Wed, 6 Mar 2019 03:56:23 -0500 Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268pqus028239; Wed, 6 Mar 2019 09:55:52 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2qygfxpr82-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:52 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0D72C3A; Wed, 6 Mar 2019 08:55:52 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id D85E323F7; Wed, 6 Mar 2019 08:55:51 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:51 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 6/8] iio: adc: stm32-dfsdm: add support for scan mode Date: Wed, 6 Mar 2019 09:55:22 +0100 Message-ID: <1551862524-25098-7-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG3NODE3.st.com (10.75.127.9) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_06:,, signatures=0 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 In order to support multiple channels in buffer mode, add support for scan mode. This is precursor patch to ease support of triggered buffer mode. Currently, only audio uses buffer mode: Regular continuous conversions with a single channel (per filter). DFSDM hardware supports scan mode (only) with injected conversions. Conversions can be launched by software (JSWSTART), trigger or synchronously with filter 0 (e.g. JSYNC). Continuous conversion mode isn't available for injected. Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-adc.c | 182 +++++++++++++++++++++++++++++--------- 1 file changed, 142 insertions(+), 40 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index b491424..4ead6bf 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -40,7 +40,8 @@ /* Filter configuration */ #define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \ - DFSDM_CR1_RSYNC_MASK) + DFSDM_CR1_RSYNC_MASK | DFSDM_CR1_JSYNC_MASK | \ + DFSDM_CR1_JSCAN_MASK) enum sd_converter_type { DFSDM_AUDIO, @@ -58,6 +59,8 @@ struct stm32_dfsdm_adc { struct stm32_dfsdm *dfsdm; const struct stm32_dfsdm_dev_data *dev_data; unsigned int fl_id; + unsigned int nconv; + unsigned long smask; /* ADC specific */ unsigned int oversamp; @@ -204,19 +207,39 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl, return 0; } -static int stm32_dfsdm_start_channel(struct stm32_dfsdm *dfsdm, - unsigned int ch_id) +static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc) { - return regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id), - DFSDM_CHCFGR1_CHEN_MASK, - DFSDM_CHCFGR1_CHEN(1)); + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct regmap *regmap = adc->dfsdm->regmap; + const struct iio_chan_spec *chan; + unsigned int bit; + int ret; + + for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) { + chan = indio_dev->channels + bit; + ret = regmap_update_bits(regmap, DFSDM_CHCFGR1(chan->channel), + DFSDM_CHCFGR1_CHEN_MASK, + DFSDM_CHCFGR1_CHEN(1)); + if (ret < 0) + return ret; + } + + return 0; } -static void stm32_dfsdm_stop_channel(struct stm32_dfsdm *dfsdm, - unsigned int ch_id) +static void stm32_dfsdm_stop_channel(struct stm32_dfsdm_adc *adc) { - regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id), - DFSDM_CHCFGR1_CHEN_MASK, DFSDM_CHCFGR1_CHEN(0)); + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct regmap *regmap = adc->dfsdm->regmap; + const struct iio_chan_spec *chan; + unsigned int bit; + + for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) { + chan = indio_dev->channels + bit; + regmap_update_bits(regmap, DFSDM_CHCFGR1(chan->channel), + DFSDM_CHCFGR1_CHEN_MASK, + DFSDM_CHCFGR1_CHEN(0)); + } } static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm, @@ -241,9 +264,10 @@ static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm, DFSDM_CHCFGR1_CHINSEL(ch->alt_si)); } -static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm, +static int stm32_dfsdm_start_filter(struct stm32_dfsdm_adc *adc, unsigned int fl_id) { + struct stm32_dfsdm *dfsdm = adc->dfsdm; int ret; /* Enable filter */ @@ -252,7 +276,11 @@ static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm, if (ret < 0) return ret; - /* Start conversion */ + /* Nothing more to do for injected (scan mode/triggered) conversions */ + if (adc->nconv > 1) + return 0; + + /* Software start (single or continuous) regular conversion */ return regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id), DFSDM_CR1_RSWSTART_MASK, DFSDM_CR1_RSWSTART(1)); @@ -267,12 +295,14 @@ static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, } static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, - unsigned int fl_id, unsigned int ch_id) + unsigned int fl_id) { struct iio_dev *indio_dev = iio_priv_to_dev(adc); struct regmap *regmap = adc->dfsdm->regmap; struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; u32 cr1; + const struct iio_chan_spec *chan; + unsigned int bit, jchg = 0; int ret; /* Average integrator oversampling */ @@ -292,14 +322,59 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, if (ret) return ret; - /* No scan mode supported for the moment */ - cr1 = DFSDM_CR1_RCH(ch_id); + /* + * DFSDM modes configuration W.R.T audio/iio type modes + * ---------------------------------------------------------------- + * Modes | regular | regular | injected | injected | + * | | continuous | | + scan | + * --------------|---------|--------------|----------|------------| + * single conv | x | | | | + * (1 chan) | | | | | + * --------------|---------|--------------|----------|------------| + * 1 Audio chan | | sample freq | | | + * | | or sync_mode | | | + * --------------|---------|--------------|----------|------------| + * 1 IIO chan | | sample freq | trigger | | + * | | or sync_mode | | | + * --------------|---------|--------------|----------|------------| + * 2+ IIO chans | | | | trigger or | + * | | | | sync_mode | + * ---------------------------------------------------------------- + */ + if (adc->nconv == 1) { + bit = __ffs(adc->smask); + chan = indio_dev->channels + bit; - /* Continuous conversions triggered by SPI clock in buffer mode */ - if (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE) - cr1 |= DFSDM_CR1_RCONT(1); + /* Use regular conversion for single channel without trigger */ + cr1 = DFSDM_CR1_RCH(chan->channel); - cr1 |= DFSDM_CR1_RSYNC(fl->sync_mode); + /* Continuous conversions triggered by SPI clk in buffer mode */ + if (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE) + cr1 |= DFSDM_CR1_RCONT(1); + + cr1 |= DFSDM_CR1_RSYNC(fl->sync_mode); + } else { + /* Use injected conversion for multiple channels */ + for_each_set_bit(bit, &adc->smask, + sizeof(adc->smask) * BITS_PER_BYTE) { + chan = indio_dev->channels + bit; + jchg |= BIT(chan->channel); + } + ret = regmap_write(regmap, DFSDM_JCHGR(fl_id), jchg); + if (ret < 0) + return ret; + + /* Use scan mode for multiple channels */ + cr1 = DFSDM_CR1_JSCAN(1); + + /* + * Continuous conversions not supported in injected mode: + * - use conversions in sync with filter 0 + */ + if (!fl->sync_mode) + return -EINVAL; + cr1 |= DFSDM_CR1_JSYNC(fl->sync_mode); + } return regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_CFG_MASK, cr1); @@ -428,21 +503,20 @@ static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev, return len; } -static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, - const struct iio_chan_spec *chan) +static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc) { struct regmap *regmap = adc->dfsdm->regmap; int ret; - ret = stm32_dfsdm_start_channel(adc->dfsdm, chan->channel); + ret = stm32_dfsdm_start_channel(adc); if (ret < 0) return ret; - ret = stm32_dfsdm_filter_configure(adc, adc->fl_id, chan->channel); + ret = stm32_dfsdm_filter_configure(adc, adc->fl_id); if (ret < 0) goto stop_channels; - ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id); + ret = stm32_dfsdm_start_filter(adc, adc->fl_id); if (ret < 0) goto filter_unconfigure; @@ -452,13 +526,12 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK, 0); stop_channels: - stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel); + stm32_dfsdm_stop_channel(adc); return ret; } -static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc, - const struct iio_chan_spec *chan) +static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc) { struct regmap *regmap = adc->dfsdm->regmap; @@ -467,7 +540,7 @@ static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc, regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), DFSDM_CR1_CFG_MASK, 0); - stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel); + stm32_dfsdm_stop_channel(adc); } static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev, @@ -557,8 +630,7 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); struct dma_slave_config config = { - .src_addr = (dma_addr_t)adc->dfsdm->phys_base + - DFSDM_RDATAR(adc->fl_id), + .src_addr = (dma_addr_t)adc->dfsdm->phys_base, .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, }; struct dma_async_tx_descriptor *desc; @@ -571,6 +643,10 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__, adc->buf_sz, adc->buf_sz / 2); + if (adc->nconv == 1) + config.src_addr += DFSDM_RDATAR(adc->fl_id); + else + config.src_addr += DFSDM_JDATAR(adc->fl_id); ret = dmaengine_slave_config(adc->dma_chan, &config); if (ret) return ret; @@ -595,9 +671,20 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) /* Issue pending DMA requests */ dma_async_issue_pending(adc->dma_chan); - /* Enable DMA transfer*/ - ret = regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RDMAEN_MASK, DFSDM_CR1_RDMAEN_MASK); + if (adc->nconv == 1) { + /* Enable regular DMA transfer*/ + ret = regmap_update_bits(adc->dfsdm->regmap, + DFSDM_CR1(adc->fl_id), + DFSDM_CR1_RDMAEN_MASK, + DFSDM_CR1_RDMAEN_MASK); + } else { + /* Enable injected DMA transfer*/ + ret = regmap_update_bits(adc->dfsdm->regmap, + DFSDM_CR1(adc->fl_id), + DFSDM_CR1_JDMAEN_MASK, + DFSDM_CR1_JDMAEN_MASK); + } + if (ret < 0) goto err_stop_dma; @@ -617,14 +704,26 @@ static void stm32_dfsdm_adc_dma_stop(struct iio_dev *indio_dev) return; regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), - DFSDM_CR1_RDMAEN_MASK, 0); + DFSDM_CR1_RDMAEN_MASK | DFSDM_CR1_JDMAEN_MASK, 0); dmaengine_terminate_all(adc->dma_chan); } +static int stm32_dfsdm_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); + + adc->nconv = bitmap_weight(scan_mask, indio_dev->masklength); + adc->smask = *scan_mask; + + dev_dbg(&indio_dev->dev, "nconv=%d mask=%lx\n", adc->nconv, *scan_mask); + + return 0; +} + static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - const struct iio_chan_spec *chan = &indio_dev->channels[0]; int ret; /* Reset adc buffer index */ @@ -646,7 +745,7 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) goto stop_dfsdm; } - ret = stm32_dfsdm_start_conv(adc, chan); + ret = stm32_dfsdm_start_conv(adc); if (ret) { dev_err(&indio_dev->dev, "Can't start conversion\n"); goto err_stop_dma; @@ -668,9 +767,8 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - const struct iio_chan_spec *chan = &indio_dev->channels[0]; - stm32_dfsdm_stop_conv(adc, chan); + stm32_dfsdm_stop_conv(adc); stm32_dfsdm_adc_dma_stop(indio_dev); @@ -756,7 +854,9 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, if (ret < 0) goto stop_dfsdm; - ret = stm32_dfsdm_start_conv(adc, chan); + adc->nconv = 1; + adc->smask = BIT(chan->scan_index); + ret = stm32_dfsdm_start_conv(adc); if (ret < 0) { regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); @@ -777,7 +877,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, else ret = IIO_VAL_INT; - stm32_dfsdm_stop_conv(adc, chan); + stm32_dfsdm_stop_conv(adc); stop_dfsdm: stm32_dfsdm_stop_dfsdm(adc->dfsdm); @@ -882,11 +982,13 @@ static const struct iio_info stm32_dfsdm_info_audio = { .hwfifo_set_watermark = stm32_dfsdm_set_watermark, .read_raw = stm32_dfsdm_read_raw, .write_raw = stm32_dfsdm_write_raw, + .update_scan_mode = stm32_dfsdm_update_scan_mode, }; static const struct iio_info stm32_dfsdm_info_adc = { .read_raw = stm32_dfsdm_read_raw, .write_raw = stm32_dfsdm_write_raw, + .update_scan_mode = stm32_dfsdm_update_scan_mode, }; static irqreturn_t stm32_dfsdm_irq(int irq, void *arg) From patchwork Wed Mar 6 08:55:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840601 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 BBB8C17E4 for ; Wed, 6 Mar 2019 08:56:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A76512BE02 for ; Wed, 6 Mar 2019 08:56:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9BDC92C23C; Wed, 6 Mar 2019 08:56:37 +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 81B9E2BE02 for ; Wed, 6 Mar 2019 08:56:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729659AbfCFI43 (ORCPT ); Wed, 6 Mar 2019 03:56:29 -0500 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:56153 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729631AbfCFI42 (ORCPT ); Wed, 6 Mar 2019 03:56:28 -0500 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268q3UI022862; Wed, 6 Mar 2019 09:55:54 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2qyhkn6rd4-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:54 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 1C54F31; Wed, 6 Mar 2019 08:55:53 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id B15B92400; Wed, 6 Mar 2019 08:55:52 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:52 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 7/8] iio: adc: stm32-dfsdm: add support for buffer modes Date: Wed, 6 Mar 2019 09:55:23 +0100 Message-ID: <1551862524-25098-8-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG6NODE2.st.com (10.75.127.17) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_05:,, signatures=0 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 DFSDM can operate using these buffer modes: - INDIO_BUFFER_SOFTWARE: regular continuous conversions (no trigger) but limited to 1 channel. User can set sampling frequency in this case. - INDIO_BUFFER_TRIGGERED: triggered conversions (injected with or without scan mode, resp for one or more channels). DFSDM can use hardware triggers (e.g. STM32 timer/lptimer), add INDIO_HARDWARE_TRIGGERED to supported modes. Only support DMA-based buffer modes. In case no DMA is available, only support INDIO_DIRECT_MODE. Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-adc.c | 218 +++++++++++++++++++++++++++++++++----- 1 file changed, 194 insertions(+), 24 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 4ead6bf..51688eb 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -12,6 +12,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -121,6 +126,61 @@ static int stm32_dfsdm_str2val(const char *str, return -EINVAL; } +/** + * struct stm32_dfsdm_trig_info - DFSDM trigger info + * @name: name of the trigger, corresponding to its source + * @jextsel: trigger signal selection + */ +struct stm32_dfsdm_trig_info { + const char *name; + unsigned int jextsel; +}; + +/* hardware injected trigger enable, edge selection */ +enum stm32_dfsdm_jexten { + STM32_DFSDM_JEXTEN_DISABLED, + STM32_DFSDM_JEXTEN_RISING_EDGE, + STM32_DFSDM_JEXTEN_FALLING_EDGE, + STM32_DFSDM_EXTEN_BOTH_EDGES, +}; + +static const struct stm32_dfsdm_trig_info stm32_dfsdm_trigs[] = { + { TIM1_TRGO, 0 }, + { TIM1_TRGO2, 1 }, + { TIM8_TRGO, 2 }, + { TIM8_TRGO2, 3 }, + { TIM3_TRGO, 4 }, + { TIM4_TRGO, 5 }, + { TIM16_OC1, 6 }, + { TIM6_TRGO, 7 }, + { TIM7_TRGO, 8 }, + { LPTIM1_OUT, 26 }, + { LPTIM2_OUT, 27 }, + { LPTIM3_OUT, 28 }, + {}, +}; + +static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + int i; + + /* lookup triggers registered by stm32 timer trigger driver */ + for (i = 0; stm32_dfsdm_trigs[i].name; i++) { + /** + * Checking both stm32 timer trigger type and trig name + * should be safe against arbitrary trigger names. + */ + if ((is_stm32_timer_trigger(trig) || + is_stm32_lptim_trigger(trig)) && + !strcmp(stm32_dfsdm_trigs[i].name, trig->name)) { + return stm32_dfsdm_trigs[i].jextsel; + } + } + + return -EINVAL; +} + static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl, unsigned int fast, unsigned int oversamp) { @@ -265,7 +325,8 @@ static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm, } static int stm32_dfsdm_start_filter(struct stm32_dfsdm_adc *adc, - unsigned int fl_id) + unsigned int fl_id, + struct iio_trigger *trig) { struct stm32_dfsdm *dfsdm = adc->dfsdm; int ret; @@ -277,7 +338,7 @@ static int stm32_dfsdm_start_filter(struct stm32_dfsdm_adc *adc, return ret; /* Nothing more to do for injected (scan mode/triggered) conversions */ - if (adc->nconv > 1) + if (adc->nconv > 1 || trig) return 0; /* Software start (single or continuous) regular conversion */ @@ -294,8 +355,38 @@ static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0)); } +static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc, + unsigned int fl_id, + struct iio_trigger *trig) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct regmap *regmap = adc->dfsdm->regmap; + u32 jextsel = 0, jexten = STM32_DFSDM_JEXTEN_DISABLED; + int ret; + + if (trig) { + ret = stm32_dfsdm_get_jextsel(indio_dev, trig); + if (ret < 0) + return ret; + + /* set trigger source and polarity (default to rising edge) */ + jextsel = ret; + jexten = STM32_DFSDM_JEXTEN_RISING_EDGE; + } + + ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), + DFSDM_CR1_JEXTSEL_MASK | DFSDM_CR1_JEXTEN_MASK, + DFSDM_CR1_JEXTSEL(jextsel) | + DFSDM_CR1_JEXTEN(jexten)); + if (ret < 0) + return ret; + + return 0; +} + static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, - unsigned int fl_id) + unsigned int fl_id, + struct iio_trigger *trig) { struct iio_dev *indio_dev = iio_priv_to_dev(adc); struct regmap *regmap = adc->dfsdm->regmap; @@ -322,6 +413,10 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, if (ret) return ret; + ret = stm32_dfsdm_filter_set_trig(adc, fl_id, trig); + if (ret) + return ret; + /* * DFSDM modes configuration W.R.T audio/iio type modes * ---------------------------------------------------------------- @@ -341,7 +436,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, * | | | | sync_mode | * ---------------------------------------------------------------- */ - if (adc->nconv == 1) { + if (adc->nconv == 1 && !trig) { bit = __ffs(adc->smask); chan = indio_dev->channels + bit; @@ -365,13 +460,15 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, return ret; /* Use scan mode for multiple channels */ - cr1 = DFSDM_CR1_JSCAN(1); + cr1 = DFSDM_CR1_JSCAN(!!(adc->nconv > 1)); /* - * Continuous conversions not supported in injected mode: - * - use conversions in sync with filter 0 + * Continuous conversions not supported in injected mode, + * either use: + * - conversions in sync with filter 0 + * - triggered conversions */ - if (!fl->sync_mode) + if (!fl->sync_mode && !trig) return -EINVAL; cr1 |= DFSDM_CR1_JSYNC(fl->sync_mode); } @@ -503,7 +600,8 @@ static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev, return len; } -static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc) +static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, + struct iio_trigger *trig) { struct regmap *regmap = adc->dfsdm->regmap; int ret; @@ -512,11 +610,11 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc) if (ret < 0) return ret; - ret = stm32_dfsdm_filter_configure(adc, adc->fl_id); + ret = stm32_dfsdm_filter_configure(adc, adc->fl_id, trig); if (ret < 0) goto stop_channels; - ret = stm32_dfsdm_start_filter(adc, adc->fl_id); + ret = stm32_dfsdm_start_filter(adc, adc->fl_id, trig); if (ret < 0) goto filter_unconfigure; @@ -548,6 +646,7 @@ static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev, { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); unsigned int watermark = DFSDM_DMA_BUFFER_SIZE / 2; + unsigned int rx_buf_sz = DFSDM_DMA_BUFFER_SIZE; /* * DMA cyclic transfers are used, buffer is split into two periods. @@ -556,7 +655,7 @@ static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev, * - one buffer (period) driver pushed to ASoC side. */ watermark = min(watermark, val * (unsigned int)(sizeof(u32))); - adc->buf_sz = watermark * 2; + adc->buf_sz = min(rx_buf_sz, watermark * 2 * adc->nconv); return 0; } @@ -586,13 +685,41 @@ static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc) return 0; } -static void stm32_dfsdm_audio_dma_buffer_done(void *data) +static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); + int available = stm32_dfsdm_adc_dma_residue(adc); + + while (available >= indio_dev->scan_bytes) { + u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi]; + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + pf->timestamp); + available -= indio_dev->scan_bytes; + adc->bufi += indio_dev->scan_bytes; + if (adc->bufi >= adc->buf_sz) + adc->bufi = 0; + } + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static void stm32_dfsdm_dma_buffer_done(void *data) { struct iio_dev *indio_dev = data; struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); int available = stm32_dfsdm_adc_dma_residue(adc); size_t old_pos; + if (indio_dev->currentmode & INDIO_BUFFER_TRIGGERED) { + iio_trigger_poll_chained(indio_dev->trig); + return; + } + /* * FIXME: In Kernel interface does not support cyclic DMA buffer,and * offers only an interface to push data samples per samples. @@ -620,6 +747,9 @@ static void stm32_dfsdm_audio_dma_buffer_done(void *data) adc->bufi = 0; old_pos = 0; } + /* regular iio buffer without trigger */ + if (adc->dev_data->type == DFSDM_IIO) + iio_push_to_buffers(indio_dev, buffer); } if (adc->cb) adc->cb(&adc->rx_buf[old_pos], adc->bufi - old_pos, @@ -643,7 +773,7 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__, adc->buf_sz, adc->buf_sz / 2); - if (adc->nconv == 1) + if (adc->nconv == 1 && !indio_dev->trig) config.src_addr += DFSDM_RDATAR(adc->fl_id); else config.src_addr += DFSDM_JDATAR(adc->fl_id); @@ -660,7 +790,7 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) if (!desc) return -EBUSY; - desc->callback = stm32_dfsdm_audio_dma_buffer_done; + desc->callback = stm32_dfsdm_dma_buffer_done; desc->callback_param = indio_dev; cookie = dmaengine_submit(desc); @@ -671,7 +801,7 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) /* Issue pending DMA requests */ dma_async_issue_pending(adc->dma_chan); - if (adc->nconv == 1) { + if (adc->nconv == 1 && !indio_dev->trig) { /* Enable regular DMA transfer*/ ret = regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), @@ -726,13 +856,19 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); int ret; + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + ret = iio_triggered_buffer_postenable(indio_dev); + if (ret < 0) + return ret; + } + /* Reset adc buffer index */ adc->bufi = 0; if (adc->hwc) { ret = iio_hw_consumer_enable(adc->hwc); if (ret < 0) - return ret; + goto err_predisable; } ret = stm32_dfsdm_start_dfsdm(adc->dfsdm); @@ -745,7 +881,7 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) goto stop_dfsdm; } - ret = stm32_dfsdm_start_conv(adc); + ret = stm32_dfsdm_start_conv(adc, indio_dev->trig); if (ret) { dev_err(&indio_dev->dev, "Can't start conversion\n"); goto err_stop_dma; @@ -760,6 +896,9 @@ static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) err_stop_hwc: if (adc->hwc) iio_hw_consumer_disable(adc->hwc); +err_predisable: + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) + iio_triggered_buffer_predisable(indio_dev); return ret; } @@ -777,6 +916,9 @@ static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) if (adc->hwc) iio_hw_consumer_disable(adc->hwc); + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) + iio_triggered_buffer_predisable(indio_dev); + return 0; } @@ -856,7 +998,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, adc->nconv = 1; adc->smask = BIT(chan->scan_index); - ret = stm32_dfsdm_start_conv(adc); + ret = stm32_dfsdm_start_conv(adc, NULL); if (ret < 0) { regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); @@ -978,6 +1120,12 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int stm32_dfsdm_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + return stm32_dfsdm_get_jextsel(indio_dev, trig) < 0 ? -EINVAL : 0; +} + static const struct iio_info stm32_dfsdm_info_audio = { .hwfifo_set_watermark = stm32_dfsdm_set_watermark, .read_raw = stm32_dfsdm_read_raw, @@ -986,9 +1134,11 @@ static const struct iio_info stm32_dfsdm_info_audio = { }; static const struct iio_info stm32_dfsdm_info_adc = { + .hwfifo_set_watermark = stm32_dfsdm_set_watermark, .read_raw = stm32_dfsdm_read_raw, .write_raw = stm32_dfsdm_write_raw, .update_scan_mode = stm32_dfsdm_update_scan_mode, + .validate_trigger = stm32_dfsdm_validate_trigger, }; static irqreturn_t stm32_dfsdm_irq(int irq, void *arg) @@ -1061,6 +1211,9 @@ static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev) return -ENOMEM; } + indio_dev->modes |= INDIO_BUFFER_SOFTWARE; + indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops; + return 0; } @@ -1082,7 +1235,8 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling */ ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); - ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | + BIT(IIO_CHAN_INFO_SAMP_FREQ); if (adc->dev_data->type == DFSDM_AUDIO) { ch->scan_type.sign = 's'; @@ -1104,9 +1258,6 @@ static int stm32_dfsdm_audio_init(struct iio_dev *indio_dev) struct stm32_dfsdm_channel *d_ch; int ret; - indio_dev->modes |= INDIO_BUFFER_SOFTWARE; - indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops; - ch = devm_kzalloc(&indio_dev->dev, sizeof(*ch), GFP_KERNEL); if (!ch) return -ENOMEM; @@ -1174,6 +1325,25 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev) init_completion(&adc->completion); + /* Optionally request DMA */ + if (stm32_dfsdm_dma_request(indio_dev)) { + dev_dbg(&indio_dev->dev, "No DMA support\n"); + return 0; + } + + ret = iio_triggered_buffer_setup(indio_dev, + &iio_pollfunc_store_time, + &stm32_dfsdm_adc_trigger_handler, + &stm32_dfsdm_buffer_setup_ops); + if (ret) { + stm32_dfsdm_dma_release(indio_dev); + dev_err(&indio_dev->dev, "buffer setup failed\n"); + return ret; + } + + /* lptimer/timer hardware triggers */ + indio_dev->modes |= INDIO_HARDWARE_TRIGGERED; + return 0; } @@ -1221,7 +1391,7 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) iio->dev.parent = dev; iio->dev.of_node = np; - iio->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + iio->modes = INDIO_DIRECT_MODE; platform_set_drvdata(pdev, adc); From patchwork Wed Mar 6 08:55:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrice Gasnier X-Patchwork-Id: 10840593 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 F09291390 for ; Wed, 6 Mar 2019 08:56:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DD80B2BE02 for ; Wed, 6 Mar 2019 08:56:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF1172C155; Wed, 6 Mar 2019 08:56:18 +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 73AD52BE02 for ; Wed, 6 Mar 2019 08:56:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729150AbfCFI4R (ORCPT ); Wed, 6 Mar 2019 03:56:17 -0500 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:20649 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728438AbfCFI4R (ORCPT ); Wed, 6 Mar 2019 03:56:17 -0500 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x268sqWW015101; Wed, 6 Mar 2019 09:55:55 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2qyhgaxr3x-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 06 Mar 2019 09:55:55 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id A8F353A; Wed, 6 Mar 2019 08:55:53 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag5node3.st.com [10.75.127.15]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 67E5E2409; Wed, 6 Mar 2019 08:55:53 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG5NODE3.st.com (10.75.127.15) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 6 Mar 2019 09:55:52 +0100 From: Fabrice Gasnier To: CC: , , , , , , , , , , , Subject: [PATCH 8/8] iio: adc: stm32-dfsdm: claim direct mode for raw read and settings Date: Wed, 6 Mar 2019 09:55:24 +0100 Message-ID: <1551862524-25098-9-git-send-email-fabrice.gasnier@st.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> References: <1551862524-25098-1-git-send-email-fabrice.gasnier@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG4NODE2.st.com (10.75.127.11) To SFHDAG5NODE3.st.com (10.75.127.15) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-03-06_04:,, signatures=0 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 Claim direct mode to ensure no buffer mode is in use for: - single conversion - sample rate setting (must be set when filter isn't enabled). - oversampling ratio (must be set when filter isn't enabled). Signed-off-by: Fabrice Gasnier --- drivers/iio/adc/stm32-dfsdm-adc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 51688eb..ca42946 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1039,16 +1039,23 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; ret = stm32_dfsdm_set_osrs(fl, 0, val); if (!ret) adc->oversamp = val; - + iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: if (!val) return -EINVAL; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + switch (ch->src) { case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: spi_freq = adc->dfsdm->spi_master_freq; @@ -1070,9 +1077,11 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, if (ret < 0) { dev_err(&indio_dev->dev, "Not able to find parameter that match!\n"); + iio_device_release_direct_mode(indio_dev); return ret; } adc->sample_freq = val; + iio_device_release_direct_mode(indio_dev); return 0; } @@ -1089,11 +1098,15 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; ret = iio_hw_consumer_enable(adc->hwc); if (ret < 0) { dev_err(&indio_dev->dev, "%s: IIO enable failed (channel %d)\n", __func__, chan->channel); + iio_device_release_direct_mode(indio_dev); return ret; } ret = stm32_dfsdm_single_conv(indio_dev, chan, val); @@ -1102,8 +1115,10 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, dev_err(&indio_dev->dev, "%s: Conversion failed (channel %d)\n", __func__, chan->channel); + iio_device_release_direct_mode(indio_dev); return ret; } + iio_device_release_direct_mode(indio_dev); return IIO_VAL_INT; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: