From patchwork Mon Jan 11 15:16:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 12010965 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B952C4332B for ; Mon, 11 Jan 2021 15:18:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 38A6522A83 for ; Mon, 11 Jan 2021 15:18:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732822AbhAKPSC (ORCPT ); Mon, 11 Jan 2021 10:18:02 -0500 Received: from mail.kernel.org ([198.145.29.99]:53966 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732254AbhAKPR7 (ORCPT ); Mon, 11 Jan 2021 10:17:59 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 6CBAB229CA; Mon, 11 Jan 2021 15:17:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1610378239; bh=63qwzC9c0LlBIqqdfrjnZd4HsZDhESbEoY3niqpxfyg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y3CO8hkTtE7BZXBnSJnv29JeOD5i2ZnKkojIQfA/pB79i6sv53lWcObDppbw5u62r CpydZDc2Lx3IwOsWEHG+RMIRJpGKr3AIa7/gtltO1UGqxXByZ1XE6LcLyENYrx/flI GhfF/72cyGL5ffo/FZQiPdGo6u7yrTiVA6s1H4PgX9LlIZy8XH6q/RH+FQFLwRW2hG yZaEmvIDknCa93OFiz0BYyeXaSItoGPLyV5XO012LERrAjJV2Ejudf3vVnXkOlh18Y FdsnLzYUo5be1HmmJRLHka6Sebu/fihtHqFLQd+6ntNy+S5zkLCG58SPE9M5IYUy5+ PZE5T3slHpppg== From: Vinod Koul To: Bjorn Andersson , Mark Brown , Wolfram Sang Cc: linux-arm-msm@vger.kernel.org, Vinod Koul , Andy Gross , Matthias Kaehlcke , Douglas Anderson , Sumit Semwal , Amit Pundir , linux-spi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/7] soc: qcom: geni: move GENI_IF_DISABLE_RO to common header Date: Mon, 11 Jan 2021 20:46:45 +0530 Message-Id: <20210111151651.1616813-2-vkoul@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210111151651.1616813-1-vkoul@kernel.org> References: <20210111151651.1616813-1-vkoul@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org GENI_IF_DISABLE_RO is used by geni spi driver as well to check the status if GENI, so move this to common header qcom-geni-se.h Signed-off-by: Vinod Koul Reviewed-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 1 - include/linux/qcom-geni-se.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index f42954e2c98e..285ed86c2bab 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -108,7 +108,6 @@ static struct geni_wrapper *earlycon_wrapper; #define GENI_OUTPUT_CTRL 0x24 #define GENI_CGC_CTRL 0x28 #define GENI_CLK_CTRL_RO 0x60 -#define GENI_IF_DISABLE_RO 0x64 #define GENI_FW_S_REVISION_RO 0x6c #define SE_GENI_BYTE_GRAN 0x254 #define SE_GENI_TX_PACKING_CFG0 0x260 diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index ec2ad4b0fe14..e3f4b16040d9 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -65,6 +65,7 @@ struct geni_se { #define SE_GENI_STATUS 0x40 #define GENI_SER_M_CLK_CFG 0x48 #define GENI_SER_S_CLK_CFG 0x4c +#define GENI_IF_DISABLE_RO 0x64 #define GENI_FW_REVISION_RO 0x68 #define SE_GENI_CLK_SEL 0x7c #define SE_GENI_DMA_MODE_EN 0x258 From patchwork Mon Jan 11 15:16:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 12010967 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0DF87C43333 for ; Mon, 11 Jan 2021 15:18:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D3935229CA for ; Mon, 11 Jan 2021 15:18:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733075AbhAKPSI (ORCPT ); Mon, 11 Jan 2021 10:18:08 -0500 Received: from mail.kernel.org ([198.145.29.99]:54002 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732254AbhAKPSI (ORCPT ); Mon, 11 Jan 2021 10:18:08 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0CA0622A83; Mon, 11 Jan 2021 15:17:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1610378247; bh=mgPG975hZ/zT7DR9gnPDc3VlS/vIBBlXErvGoIyOQWs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CEU/R6qRPr5KhtJFMPm17zQv7HLG6IaERWmPfyAX+1j3ziELESpn8Jfmv38x6wngQ QVSXOnFmqxwcjWSEocK7IwNRO6mWPo8EOLXTcH7spsoKGiBGxZ+Cxa1dO68MVN8EAr zDB5+vsWo9uc42skVoiaqbGeUGXvuT7ugiryLoIXn1U74+ICw1vHy1bgATy2Ui8UNv kdMnNc8xjmrJiFLzdYxSt3W65LYJdoixUPIsOiKVetdIHK9DNDyjEOpvjOMIxQaxZW NxDVhfhUjP3lEcja809HaEWeZ//NekLEWwN5W0wAy5+mHh3bw7ZvuUiZCB1O+EMKAt U42i/cUB8ctew== From: Vinod Koul To: Bjorn Andersson , Mark Brown , Wolfram Sang Cc: linux-arm-msm@vger.kernel.org, Vinod Koul , Andy Gross , Matthias Kaehlcke , Douglas Anderson , Sumit Semwal , Amit Pundir , linux-spi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/7] soc: qcom: geni: move struct geni_wrapper to header Date: Mon, 11 Jan 2021 20:46:46 +0530 Message-Id: <20210111151651.1616813-3-vkoul@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210111151651.1616813-1-vkoul@kernel.org> References: <20210111151651.1616813-1-vkoul@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org I2C geni driver needs to access struct geni_wrapper, so move it to header. Signed-off-by: Vinod Koul --- drivers/soc/qcom/qcom-geni-se.c | 15 --------------- include/linux/qcom-geni-se.h | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 285ed86c2bab..a3868228ea05 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -79,21 +79,6 @@ */ #define MAX_CLK_PERF_LEVEL 32 -#define NUM_AHB_CLKS 2 - -/** - * struct geni_wrapper - Data structure to represent the QUP Wrapper Core - * @dev: Device pointer of the QUP wrapper core - * @base: Base address of this instance of QUP wrapper core - * @ahb_clks: Handle to the primary & secondary AHB clocks - * @to_core: Core ICC path - */ -struct geni_wrapper { - struct device *dev; - void __iomem *base; - struct clk_bulk_data ahb_clks[NUM_AHB_CLKS]; - struct geni_icc_path to_core; -}; static const char * const icc_path_names[] = {"qup-core", "qup-config", "qup-memory"}; diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index e3f4b16040d9..cb4e40908f9f 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -38,6 +38,21 @@ struct geni_icc_path { unsigned int avg_bw; }; +#define NUM_AHB_CLKS 2 + +/** + * @struct geni_wrapper - Data structure to represent the QUP Wrapper Core + * @dev: Device pointer of the QUP wrapper core + * @base: Base address of this instance of QUP wrapper core + * @ahb_clks: Handle to the primary & secondary AHB clocks + */ +struct geni_wrapper { + struct device *dev; + void __iomem *base; + struct clk_bulk_data ahb_clks[NUM_AHB_CLKS]; + struct geni_icc_path to_core; +}; + /** * struct geni_se - GENI Serial Engine * @base: Base Address of the Serial Engine's register block From patchwork Mon Jan 11 15:16:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 12010969 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72BB7C433DB for ; Mon, 11 Jan 2021 15:18:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2A670229CA for ; Mon, 11 Jan 2021 15:18:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733022AbhAKPSQ (ORCPT ); Mon, 11 Jan 2021 10:18:16 -0500 Received: from mail.kernel.org ([198.145.29.99]:54022 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731411AbhAKPSP (ORCPT ); Mon, 11 Jan 2021 10:18:15 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 3BC4B22AAD; Mon, 11 Jan 2021 15:17:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1610378254; bh=1RM1BNZzHpaIt39vBzX76yfWIxdh0luCR0ga/vWK/ec=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gUo4RjYUF6So50ry4Kljg0Lh0EN2z9jSL/8wef0YtlLccXbdU6he29iMYAu63AOnL Dzlep5gKJgmUXBwhzjS566L7WqiXmFxeE3T7YXJJEPPYsPgWVtZ5K3jn5u0z6MUZ7e L7jx4TJB2yGeJoxcDq8fKpn+tmfoCqrH+rPG69hC0pENgIWVhX0ntpHQkqHjTE+eW/ 7rZ87ynuKk1GW9VX2UYxVE2bCf01bNEG86VVqdp+8sMekWLSBqocno9SdmIIhTAF5m w3CvnubgnyApx8l+A6BQrxVHEtokaXFQHMtsoCIvO//WhCGS96PydXAnWRVx+W5to6 KFyK1JiXjmZjQ== From: Vinod Koul To: Bjorn Andersson , Mark Brown , Wolfram Sang Cc: linux-arm-msm@vger.kernel.org, Vinod Koul , Andy Gross , Matthias Kaehlcke , Douglas Anderson , Sumit Semwal , Amit Pundir , linux-spi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/7] soc: qcom: geni: Add support for gpi dma Date: Mon, 11 Jan 2021 20:46:47 +0530 Message-Id: <20210111151651.1616813-4-vkoul@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210111151651.1616813-1-vkoul@kernel.org> References: <20210111151651.1616813-1-vkoul@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org GPI DMA is one of the DMA modes supported on geni, this adds support to enable that mode Signed-off-by: Vinod Koul --- drivers/soc/qcom/qcom-geni-se.c | 39 ++++++++++++++++++++++++++++++++- include/linux/qcom-geni-se.h | 4 ++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index a3868228ea05..db44dc32e049 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -310,6 +310,39 @@ static void geni_se_select_dma_mode(struct geni_se *se) writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); } +static int geni_se_select_gpi_mode(struct geni_se *se) +{ + unsigned int geni_dma_mode = 0; + unsigned int gpi_event_en = 0; + unsigned int common_geni_m_irq_en = 0; + unsigned int common_geni_s_irq_en = 0; + + common_geni_m_irq_en = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); + common_geni_s_irq_en = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); + common_geni_m_irq_en &= + ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN | + M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); + common_geni_s_irq_en &= ~S_CMD_DONE_EN; + geni_dma_mode = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); + gpi_event_en = readl_relaxed(se->base + SE_GSI_EVENT_EN); + + geni_dma_mode |= GENI_DMA_MODE_EN; + gpi_event_en |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | + GENI_M_EVENT_EN | GENI_S_EVENT_EN); + + writel_relaxed(0, se->base + SE_IRQ_EN); + writel_relaxed(common_geni_s_irq_en, se->base + SE_GENI_S_IRQ_EN); + writel_relaxed(common_geni_m_irq_en, se->base + SE_GENI_M_IRQ_EN); + writel_relaxed(0xFFFFFFFF, se->base + SE_GENI_M_IRQ_CLEAR); + writel_relaxed(0xFFFFFFFF, se->base + SE_GENI_S_IRQ_CLEAR); + writel_relaxed(0xFFFFFFFF, se->base + SE_DMA_TX_IRQ_CLR); + writel_relaxed(0xFFFFFFFF, se->base + SE_DMA_RX_IRQ_CLR); + writel_relaxed(geni_dma_mode, se->base + SE_GENI_DMA_MODE_EN); + writel_relaxed(gpi_event_en, se->base + SE_GSI_EVENT_EN); + + return 0; +} + /** * geni_se_select_mode() - Select the serial engine transfer mode * @se: Pointer to the concerned serial engine. @@ -317,7 +350,8 @@ static void geni_se_select_dma_mode(struct geni_se *se) */ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode) { - WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA); + WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA && + mode != GENI_GPI_DMA); switch (mode) { case GENI_SE_FIFO: @@ -326,6 +360,9 @@ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode) case GENI_SE_DMA: geni_se_select_dma_mode(se); break; + case GENI_GPI_DMA: + geni_se_select_gpi_mode(se); + break; case GENI_SE_INVALID: default: break; diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index cb4e40908f9f..12003a6cb133 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -12,6 +12,7 @@ enum geni_se_xfer_mode { GENI_SE_INVALID, GENI_SE_FIFO, + GENI_GPI_DMA, GENI_SE_DMA, }; @@ -123,6 +124,9 @@ struct geni_se { #define CLK_DIV_MSK GENMASK(15, 4) #define CLK_DIV_SHFT 4 +/* GENI_IF_DISABLE_RO fields */ +#define FIFO_IF_DISABLE (BIT(0)) + /* GENI_FW_REVISION_RO fields */ #define FW_REV_PROTOCOL_MSK GENMASK(15, 8) #define FW_REV_PROTOCOL_SHFT 8 From patchwork Mon Jan 11 15:16:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 12010971 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 88A4EC4332D for ; Mon, 11 Jan 2021 15:18:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4AF2D229CA for ; Mon, 11 Jan 2021 15:18:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731918AbhAKPSY (ORCPT ); Mon, 11 Jan 2021 10:18:24 -0500 Received: from mail.kernel.org ([198.145.29.99]:54084 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731411AbhAKPSX (ORCPT ); Mon, 11 Jan 2021 10:18:23 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 31E9C22AAF; Mon, 11 Jan 2021 15:17:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1610378262; bh=Dj4wFh5vS16qByBNkr4HY1a6D1zgNungXmamdi5kJ1E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=loYNRs4XdluA7qvIhaXmWzCfbZ3ueVd9DFq5fHVJrzOBYuBmlmOQtDt69kOqmr3/m vJgzXfkbI0Hv1ETso+vKqOKjBrwHpiwNy9BvLv9J6Ch7tI3+a4ZpmuUW9r8Yv+RZM3 LzE0+9H2UENmTLi81lg04Hn9FpcXiWWKcwi7DEBVE8xLCNAxf5RQL5x/wbZgGv4iUX wanvy5Q+116AHmqL1ah3fD1i0UmkOCTOkI3q+zNYcvDRQYlqFu2HoGh1bgGUdk8aGt 95k9yGG/ccZm6io7pVDeVGUqKIlAQsf9FPcFVLHJbVEsqHfGlRD1xGTeF5jTUCrEb+ T3QSwsdPw8Ltw== From: Vinod Koul To: Bjorn Andersson , Mark Brown , Wolfram Sang Cc: linux-arm-msm@vger.kernel.org, Vinod Koul , Andy Gross , Matthias Kaehlcke , Douglas Anderson , Sumit Semwal , Amit Pundir , linux-spi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/7] spi: spi-geni-qcom: Add support for GPI dma Date: Mon, 11 Jan 2021 20:46:48 +0530 Message-Id: <20210111151651.1616813-5-vkoul@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210111151651.1616813-1-vkoul@kernel.org> References: <20210111151651.1616813-1-vkoul@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org We can use GPI DMA for devices where it is enabled by firmware. Add support for this mode Signed-off-by: Vinod Koul --- drivers/spi/spi-geni-qcom.c | 395 +++++++++++++++++++++++++++++++++++- 1 file changed, 384 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 512e925d5ea4..5bb0e2192734 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -2,6 +2,8 @@ // Copyright (c) 2017-2018, The Linux foundation. All rights reserved. #include +#include +#include #include #include #include @@ -10,6 +12,7 @@ #include #include #include +#include #include #include @@ -63,6 +66,35 @@ #define TIMESTAMP_AFTER BIT(3) #define POST_CMD_DELAY BIT(4) +#define GSI_LOOPBACK_EN (BIT(0)) +#define GSI_CS_TOGGLE (BIT(3)) +#define GSI_CPHA (BIT(4)) +#define GSI_CPOL (BIT(5)) + +#define MAX_TX_SG (3) +#define NUM_SPI_XFER (8) +#define SPI_XFER_TIMEOUT_MS (250) + +struct gsi_desc_cb { + struct spi_geni_master *mas; + struct spi_transfer *xfer; +}; + +struct spi_geni_gsi { + dma_cookie_t tx_cookie; + dma_cookie_t rx_cookie; + struct dma_async_tx_descriptor *tx_desc; + struct dma_async_tx_descriptor *rx_desc; + struct gsi_desc_cb desc_cb; +}; + +enum spi_m_cmd_opcode { + CMD_NONE, + CMD_XFER, + CMD_CS, + CMD_CANCEL, +}; + struct spi_geni_master { struct geni_se se; struct device *dev; @@ -79,10 +111,21 @@ struct spi_geni_master { struct completion cs_done; struct completion cancel_done; struct completion abort_done; + struct completion xfer_done; unsigned int oversampling; spinlock_t lock; int irq; bool cs_flag; + struct spi_geni_gsi *gsi; + struct dma_chan *tx; + struct dma_chan *rx; + struct completion tx_cb; + struct completion rx_cb; + bool qn_err; + int cur_xfer_mode; + int num_tx_eot; + int num_rx_eot; + int num_xfers; }; static int get_spi_clk_cfg(unsigned int speed_hz, @@ -274,31 +317,269 @@ static int setup_fifo_params(struct spi_device *spi_slv, return geni_spi_set_clock_and_bw(mas, spi_slv->max_speed_hz); } +static int get_xfer_mode(struct spi_master *spi) +{ + struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct geni_se *se = &mas->se; + int mode = GENI_SE_FIFO; + int fifo_disable; + bool dma_chan_valid; + + fifo_disable = readl(se->base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE; + dma_chan_valid = !(IS_ERR_OR_NULL(mas->tx) || IS_ERR_OR_NULL(mas->rx)); + + /* + * If FIFO Interface is disabled and there are no DMA channels then we + * can't do this transfer. + * If FIFO interface is disabled, we can do GSI only, + * else pick FIFO mode. + */ + if (fifo_disable && !dma_chan_valid) { + dev_err(mas->dev, "Fifo and dma mode disabled!! can't xfer\n"); + mode = -EINVAL; + } else if (fifo_disable) { + mode = GENI_GPI_DMA; + } else { + mode = GENI_SE_FIFO; + } + + return mode; +} + +static void +spi_gsi_callback_result(void *cb, const struct dmaengine_result *result, bool tx) +{ + struct gsi_desc_cb *gsi = cb; + + if (result->result != DMA_TRANS_NOERROR) { + dev_err(gsi->mas->dev, "%s: DMA %s txn failed\n", __func__, tx ? "tx" : "rx"); + return; + } + + if (!result->residue) { + dev_dbg(gsi->mas->dev, "%s\n", __func__); + if (tx) + complete(&gsi->mas->tx_cb); + else + complete(&gsi->mas->rx_cb); + } else { + dev_err(gsi->mas->dev, "DMA xfer has pending: %d\n", result->residue); + } +} + +static void +spi_gsi_rx_callback_result(void *cb, const struct dmaengine_result *result) +{ + spi_gsi_callback_result(cb, result, false); +} + +static void +spi_gsi_tx_callback_result(void *cb, const struct dmaengine_result *result) +{ + spi_gsi_callback_result(cb, result, true); +} + +static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas, + struct spi_device *spi_slv, struct spi_master *spi) +{ + int ret = 0; + unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + struct spi_geni_gsi *gsi; + struct dma_slave_config config; + struct gpi_spi_config peripheral; + + memset(&config, 0, sizeof(config)); + memset(&peripheral, 0, sizeof(peripheral)); + config.peripheral_config = &peripheral; + config.peripheral_size = sizeof(peripheral); + + if (xfer->bits_per_word != mas->cur_bits_per_word || + xfer->speed_hz != mas->cur_speed_hz) { + mas->cur_bits_per_word = xfer->bits_per_word; + mas->cur_speed_hz = xfer->speed_hz; + peripheral.set_config = true; + } + + if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) { + peripheral.rx_len = ((xfer->len << 3) / mas->cur_bits_per_word); + } else { + int bytes_per_word = (mas->cur_bits_per_word / BITS_PER_BYTE) + 1; + + peripheral.rx_len = (xfer->len / bytes_per_word); + } + + if (xfer->tx_buf && xfer->rx_buf) { + peripheral.cmd = SPI_DUPLEX; + } else if (xfer->tx_buf) { + peripheral.cmd = SPI_TX; + peripheral.rx_len = 0; + } else if (xfer->rx_buf) { + peripheral.cmd = SPI_RX; + } + + peripheral.cs = spi_slv->chip_select; + + if (spi_slv->mode & SPI_LOOP) + peripheral.loopback_en = true; + if (spi_slv->mode & SPI_CPOL) + peripheral.clock_pol_high = true; + if (spi_slv->mode & SPI_CPHA) + peripheral.data_pol_high = true; + peripheral.pack_en = true; + peripheral.word_len = xfer->bits_per_word - MIN_WORD_LEN; + ret = get_spi_clk_cfg(mas->cur_speed_hz, mas, + &peripheral.clk_src, &peripheral.clk_div); + if (ret) { + dev_err(mas->dev, "%s:Err setting clks:%d\n", __func__, ret); + return ret; + } + + if (!xfer->cs_change) { + if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers)) + peripheral.fragmentation = FRAGMENTATION; + } + + gsi = &mas->gsi[mas->num_xfers]; + gsi->desc_cb.mas = mas; + gsi->desc_cb.xfer = xfer; + if (peripheral.cmd & SPI_RX) { + dmaengine_slave_config(mas->rx, &config); + gsi->rx_desc = dmaengine_prep_slave_single(mas->rx, xfer->rx_dma, + xfer->len, DMA_DEV_TO_MEM, flags); + if (IS_ERR_OR_NULL(gsi->rx_desc)) { + dev_err(mas->dev, "Err setting up rx desc\n"); + return -EIO; + } + gsi->rx_desc->callback_result = spi_gsi_rx_callback_result; + gsi->rx_desc->callback_param = &gsi->desc_cb; + mas->num_rx_eot++; + } + + if (peripheral.cmd & SPI_TX_ONLY) + mas->num_tx_eot++; + + dmaengine_slave_config(mas->tx, &config); + gsi->tx_desc = dmaengine_prep_slave_single(mas->tx, xfer->tx_dma, + xfer->len, DMA_MEM_TO_DEV, flags); + + if (IS_ERR_OR_NULL(gsi->tx_desc)) { + dev_err(mas->dev, "Err setting up tx desc\n"); + return -EIO; + } + gsi->tx_desc->callback_result = spi_gsi_tx_callback_result; + gsi->tx_desc->callback_param = &gsi->desc_cb; + if (peripheral.cmd & SPI_RX) + gsi->rx_cookie = dmaengine_submit(gsi->rx_desc); + gsi->tx_cookie = dmaengine_submit(gsi->tx_desc); + if (peripheral.cmd & SPI_RX) + dma_async_issue_pending(mas->rx); + dma_async_issue_pending(mas->tx); + mas->num_xfers++; + return ret; +} + +static int spi_geni_map_buf(struct spi_geni_master *mas, struct spi_message *msg) +{ + struct spi_transfer *xfer; + struct device *gsi_dev = mas->dev->parent; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (xfer->rx_buf) { + xfer->rx_dma = dma_map_single(gsi_dev, xfer->rx_buf, + xfer->len, DMA_FROM_DEVICE); + if (dma_mapping_error(mas->dev, xfer->rx_dma)) { + dev_err(mas->dev, "Err mapping buf\n"); + return -ENOMEM; + } + } + + if (xfer->tx_buf) { + xfer->tx_dma = dma_map_single(gsi_dev, (void *)xfer->tx_buf, + xfer->len, DMA_TO_DEVICE); + if (dma_mapping_error(gsi_dev, xfer->tx_dma)) { + dev_err(mas->dev, "Err mapping buf\n"); + dma_unmap_single(gsi_dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE); + return -ENOMEM; + } + } + }; + + return 0; +} + +static void spi_geni_unmap_buf(struct spi_geni_master *mas, struct spi_message *msg) +{ + struct spi_transfer *xfer; + struct device *gsi_dev = mas->dev; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (xfer->rx_buf) + dma_unmap_single(gsi_dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE); + if (xfer->tx_buf) + dma_unmap_single(gsi_dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE); + }; +} + static int spi_geni_prepare_message(struct spi_master *spi, struct spi_message *spi_msg) { int ret; struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct geni_se *se = &mas->se; + + mas->cur_xfer_mode = get_xfer_mode(spi); + + if (mas->cur_xfer_mode == GENI_SE_FIFO) { + geni_se_select_mode(se, GENI_SE_FIFO); + reinit_completion(&mas->xfer_done); + ret = setup_fifo_params(spi_msg->spi, spi); + if (ret) + dev_err(mas->dev, "Couldn't select mode %d\n", ret); + + } else if (mas->cur_xfer_mode == GENI_GPI_DMA) { + mas->num_tx_eot = 0; + mas->num_rx_eot = 0; + mas->num_xfers = 0; + reinit_completion(&mas->tx_cb); + reinit_completion(&mas->rx_cb); + memset(mas->gsi, 0, (sizeof(struct spi_geni_gsi) * NUM_SPI_XFER)); + geni_se_select_mode(se, GENI_GPI_DMA); + ret = spi_geni_map_buf(mas, spi_msg); + + } else { + dev_err(mas->dev, "%s: Couldn't select mode %d", __func__, mas->cur_xfer_mode); + ret = -EINVAL; + } - ret = setup_fifo_params(spi_msg->spi, spi); - if (ret) - dev_err(mas->dev, "Couldn't select mode %d\n", ret); return ret; } +static int spi_geni_unprepare_message(struct spi_master *spi_mas, struct spi_message *spi_msg) +{ + struct spi_geni_master *mas = spi_master_get_devdata(spi_mas); + + mas->cur_speed_hz = 0; + mas->cur_bits_per_word = 0; + if (mas->cur_xfer_mode == GENI_GPI_DMA) + spi_geni_unmap_buf(mas, spi_msg); + return 0; +} + static int spi_geni_init(struct spi_geni_master *mas) { struct geni_se *se = &mas->se; unsigned int proto, major, minor, ver; u32 spi_tx_cfg; + size_t gsi_sz; + int ret = 0; pm_runtime_get_sync(mas->dev); proto = geni_se_read_proto(se); if (proto != GENI_SE_SPI) { dev_err(mas->dev, "Invalid proto %d\n", proto); - pm_runtime_put(mas->dev); - return -ENXIO; + ret = -ENXIO; + goto out_pm; } mas->tx_fifo_depth = geni_se_get_tx_fifo_depth(se); @@ -328,8 +609,34 @@ static int spi_geni_init(struct spi_geni_master *mas) spi_tx_cfg &= ~CS_TOGGLE; writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG); + mas->tx = dma_request_slave_channel(mas->dev, "tx"); + if (IS_ERR_OR_NULL(mas->tx)) { + dev_err(mas->dev, "Failed to get tx DMA ch %ld", PTR_ERR(mas->tx)); + ret = PTR_ERR(mas->tx); + goto out_pm; + } else { + mas->rx = dma_request_slave_channel(mas->dev, "rx"); + if (IS_ERR_OR_NULL(mas->rx)) { + dev_err(mas->dev, "Failed to get rx DMA ch %ld", PTR_ERR(mas->rx)); + dma_release_channel(mas->tx); + ret = PTR_ERR(mas->rx); + goto out_pm; + } + + gsi_sz = sizeof(struct spi_geni_gsi) * NUM_SPI_XFER; + mas->gsi = devm_kzalloc(mas->dev, gsi_sz, GFP_KERNEL); + if (IS_ERR_OR_NULL(mas->gsi)) { + dma_release_channel(mas->tx); + dma_release_channel(mas->rx); + mas->tx = NULL; + mas->rx = NULL; + goto out_pm; + } + } + +out_pm: pm_runtime_put(mas->dev); - return 0; + return ret; } static unsigned int geni_byte_per_fifo_word(struct spi_geni_master *mas) @@ -420,6 +727,7 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, { u32 m_cmd = 0; u32 len; + u32 m_param = 0; struct geni_se *se = &mas->se; int ret; @@ -457,6 +765,11 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1); len &= TRANS_LEN_MSK; + if (!xfer->cs_change) { + if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers)) + m_param |= FRAGMENTATION; + } + mas->cur_xfer = xfer; if (xfer->tx_buf) { m_cmd |= SPI_TX_ONLY; @@ -475,7 +788,7 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, * interrupt could come in at any time now. */ spin_lock_irq(&mas->lock); - geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION); + geni_se_setup_m_cmd(se, m_cmd, m_param); /* * TX_WATERMARK_REG should be set after SPI configuration and @@ -494,13 +807,52 @@ static int spi_geni_transfer_one(struct spi_master *spi, struct spi_transfer *xfer) { struct spi_geni_master *mas = spi_master_get_devdata(spi); + unsigned long timeout, jiffies; + int ret = 0i, i; /* Terminate and return success for 0 byte length transfer */ if (!xfer->len) - return 0; + return ret; + + if (mas->cur_xfer_mode == GENI_SE_FIFO) { + setup_fifo_xfer(xfer, mas, slv->mode, spi); + } else { + setup_gsi_xfer(xfer, mas, slv, spi); + if (mas->num_xfers >= NUM_SPI_XFER || + (list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))) { + for (i = 0 ; i < mas->num_tx_eot; i++) { + jiffies = msecs_to_jiffies(SPI_XFER_TIMEOUT_MS); + timeout = wait_for_completion_timeout(&mas->tx_cb, jiffies); + if (timeout <= 0) { + dev_err(mas->dev, "Tx[%d] timeout%lu\n", i, timeout); + ret = -ETIMEDOUT; + goto err_gsi_geni_transfer_one; + } + spi_finalize_current_transfer(spi); + } + for (i = 0 ; i < mas->num_rx_eot; i++) { + jiffies = msecs_to_jiffies(SPI_XFER_TIMEOUT_MS); + timeout = wait_for_completion_timeout(&mas->tx_cb, jiffies); + if (timeout <= 0) { + dev_err(mas->dev, "Rx[%d] timeout%lu\n", i, timeout); + ret = -ETIMEDOUT; + goto err_gsi_geni_transfer_one; + } + spi_finalize_current_transfer(spi); + } + if (mas->qn_err) { + ret = -EIO; + mas->qn_err = false; + goto err_gsi_geni_transfer_one; + } + } + } - setup_fifo_xfer(xfer, mas, slv->mode, spi); - return 1; + return ret; + +err_gsi_geni_transfer_one: + dmaengine_terminate_all(mas->tx); + return ret; } static irqreturn_t geni_spi_isr(int irq, void *data) @@ -595,6 +947,15 @@ static int spi_geni_probe(struct platform_device *pdev) if (irq < 0) return irq; + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (ret) { + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "could not set DMA mask\n"); + return ret; + } + } + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); @@ -632,15 +993,18 @@ static int spi_geni_probe(struct platform_device *pdev) spi->num_chipselect = 4; spi->max_speed_hz = 50000000; spi->prepare_message = spi_geni_prepare_message; + spi->unprepare_message = spi_geni_unprepare_message; spi->transfer_one = spi_geni_transfer_one; spi->auto_runtime_pm = true; spi->handle_err = handle_fifo_timeout; - spi->set_cs = spi_geni_set_cs; spi->use_gpio_descriptors = true; init_completion(&mas->cs_done); init_completion(&mas->cancel_done); init_completion(&mas->abort_done); + init_completion(&mas->xfer_done); + init_completion(&mas->tx_cb); + init_completion(&mas->rx_cb); spin_lock_init(&mas->lock); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 250); @@ -661,6 +1025,15 @@ static int spi_geni_probe(struct platform_device *pdev) if (ret) goto spi_geni_probe_runtime_disable; + /* + * query the mode supported and set_cs for fifo mode only + * for dma (gsi) mode, the gsi will set cs based on params passed in + * TRE + */ + mas->cur_xfer_mode = get_xfer_mode(spi); + if (mas->cur_xfer_mode == GENI_SE_FIFO) + spi->set_cs = spi_geni_set_cs; + ret = request_irq(mas->irq, geni_spi_isr, 0, dev_name(dev), spi); if (ret) goto spi_geni_probe_runtime_disable; From patchwork Mon Jan 11 15:16:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 12010973 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 617B5C433E0 for ; Mon, 11 Jan 2021 15:18:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 37C85229CA for ; Mon, 11 Jan 2021 15:18:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731411AbhAKPSd (ORCPT ); Mon, 11 Jan 2021 10:18:33 -0500 Received: from mail.kernel.org ([198.145.29.99]:54120 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727180AbhAKPSc (ORCPT ); Mon, 11 Jan 2021 10:18:32 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7A2E122B51; Mon, 11 Jan 2021 15:17:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1610378269; bh=ZQ1HTaI/4niGy9XYuINyoGdYNss5o6voIwBStPWoIrI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S7fDLySxbsrsWoQ8YvrpfT7DW7GMGD3JVwPUn1fA5hvPyxHEUyE+c7erRtDw0TBl0 asZp3g8Vu2cD71zExJ4sOfF3ylJWtTdVBnFNukVZdBo8zH/PPNTsw9BsOn0zxkCfjm cHBRPIujuBUSqCSUo/ij6B3chOTmvy+FyjqWQC4UkD3nAW9xuphzA70lBC+rPN9bBC MSjWST5n3o5khiZNHCNaXb9y52bgt07F/1ehBPAsXm0JaYrNKb9wPhJ7mqzkm5eFUr VuU7zXSvQTKdrbQFyBZFp3dbLgAHeQH260ckneUOq/kZXCMpaLkYTh/FoaKUI33iO3 JUXZpA2UtsxOA== From: Vinod Koul To: Bjorn Andersson , Mark Brown , Wolfram Sang Cc: linux-arm-msm@vger.kernel.org, Vinod Koul , Andy Gross , Matthias Kaehlcke , Douglas Anderson , Sumit Semwal , Amit Pundir , linux-spi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/7] i2c: qcom-geni: Add support for GPI DMA Date: Mon, 11 Jan 2021 20:46:49 +0530 Message-Id: <20210111151651.1616813-6-vkoul@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210111151651.1616813-1-vkoul@kernel.org> References: <20210111151651.1616813-1-vkoul@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org This adds capability to use GSI DMA for I2C transfers Signed-off-by: Vinod Koul --- drivers/i2c/busses/i2c-qcom-geni.c | 246 ++++++++++++++++++++++++++++- 1 file changed, 244 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 046d241183c5..6978480fb4d1 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -12,7 +12,9 @@ #include #include #include +#include #include +#include #include #define SE_I2C_TX_TRANS_LEN 0x26c @@ -48,6 +50,8 @@ #define LOW_COUNTER_SHFT 10 #define CYCLE_COUNTER_MSK GENMASK(9, 0) +#define I2C_PACK_EN (BIT(0) | BIT(1)) + enum geni_i2c_err_code { GP_IRQ0, NACK, @@ -72,6 +76,12 @@ enum geni_i2c_err_code { #define XFER_TIMEOUT HZ #define RST_TIMEOUT HZ +enum i2c_se_mode { + UNINITIALIZED, + FIFO_SE_DMA, + GSI_ONLY, +}; + struct geni_i2c_dev { struct geni_se se; u32 tx_wm; @@ -86,6 +96,17 @@ struct geni_i2c_dev { u32 clk_freq_out; const struct geni_i2c_clk_fld *clk_fld; int suspended; + struct dma_chan *tx_c; + struct dma_chan *rx_c; + dma_cookie_t rx_cookie, tx_cookie; + dma_addr_t tx_ph; + dma_addr_t rx_ph; + int cfg_sent; + struct dma_async_tx_descriptor *tx_desc; + struct dma_async_tx_descriptor *rx_desc; + enum i2c_se_mode se_mode; + bool cmd_done; + bool is_shared; }; struct geni_i2c_err_log { @@ -429,6 +450,183 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, return gi2c->err; } +static void i2c_gsi_cb_result(void *cb, const struct dmaengine_result *result) +{ + struct geni_i2c_dev *gi2c = cb; + + if (result->result != DMA_TRANS_NOERROR) { + dev_err(gi2c->se.dev, "DMA txn failed:%d\n", result->result); + return; + } + + if (result->residue) + dev_dbg(gi2c->se.dev, "DMA xfer has pending: %d\n", result->residue); + + complete(&gi2c->done); +} + +static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + int num) +{ + struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap); + struct dma_slave_config config; + struct gpi_i2c_config peripheral; + int i, ret = 0, timeout = 0; + + memset(&config, 0, sizeof(config)); + memset(&peripheral, 0, sizeof(peripheral)); + config.peripheral_config = &peripheral; + config.peripheral_size = sizeof(peripheral); + + if (!gi2c->tx_c) { + gi2c->tx_c = dma_request_slave_channel(gi2c->se.dev, "tx"); + if (!gi2c->tx_c) { + dev_err(gi2c->se.dev, "tx dma_request_slave_channel fail\n"); + ret = -EIO; + goto geni_i2c_gsi_xfer_out; + } + } + + if (!gi2c->rx_c) { + gi2c->rx_c = dma_request_slave_channel(gi2c->se.dev, "rx"); + if (!gi2c->rx_c) { + dev_err(gi2c->se.dev, "rx dma_request_slave_channel fail\n"); + ret = -EIO; + goto geni_i2c_gsi_xfer_out; + } + } + + if (!gi2c->cfg_sent) { + const struct geni_i2c_clk_fld *itr = gi2c->clk_fld; + + peripheral.pack_enable = I2C_PACK_EN; + peripheral.cycle_count = itr->t_cycle_cnt; + peripheral.high_count = itr->t_high_cnt; + peripheral.low_count = itr->t_low_cnt; + peripheral.clk_div = itr->clk_div; + gi2c->cfg_sent = true; + peripheral.set_config = true; + } + + peripheral.multi_msg = false; + for (i = 0; i < num; i++) { + struct device *rx_dev = gi2c->se.wrapper->dev; + struct device *tx_dev = gi2c->se.wrapper->dev; + int stretch = (i < (num - 1)); + u8 *dma_buf = NULL; + unsigned int flags; + + gi2c->cur = &msgs[i]; + + peripheral.addr = msgs[i].addr; + peripheral.stretch = stretch; + if (msgs[i].flags & I2C_M_RD) + peripheral.op = I2C_READ; + else + peripheral.op = I2C_WRITE; + + dma_buf = i2c_get_dma_safe_msg_buf(&msgs[i], 1); + if (!dma_buf) { + ret = -ENOMEM; + goto geni_i2c_gsi_xfer_out; + } + + if (msgs[i].flags & I2C_M_RD) { + gi2c->rx_ph = dma_map_single(rx_dev, dma_buf, + msgs[i].len, DMA_FROM_DEVICE); + if (dma_mapping_error(rx_dev, gi2c->rx_ph)) { + dev_err(gi2c->se.dev, "dma_map_single for rx failed :%d\n", ret); + i2c_put_dma_safe_msg_buf(dma_buf, &msgs[i], false); + goto geni_i2c_gsi_xfer_out; + } + + peripheral.op = I2C_READ; + peripheral.stretch = stretch; + ret = dmaengine_slave_config(gi2c->rx_c, &config); + if (ret) { + dev_err(gi2c->se.dev, "rx dma config error:%d\n", ret); + goto geni_i2c_gsi_xfer_out; + } + peripheral.set_config = false; + peripheral.multi_msg = true; + peripheral.rx_len = msgs[i].len; + + flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + gi2c->rx_desc = dmaengine_prep_slave_single(gi2c->rx_c, gi2c->rx_ph, + msgs[i].len, + DMA_DEV_TO_MEM, flags); + if (!gi2c->rx_desc) { + dev_err(gi2c->se.dev, "prep_slave_sg for rx failed\n"); + gi2c->err = -EIO; + goto geni_i2c_err_prep_sg; + } + + gi2c->rx_desc->callback_result = i2c_gsi_cb_result; + gi2c->rx_desc->callback_param = gi2c; + + /* Issue RX */ + gi2c->rx_cookie = dmaengine_submit(gi2c->rx_desc); + dma_async_issue_pending(gi2c->rx_c); + } + + dev_dbg(gi2c->se.dev, "msg[%d].len:%d W\n", i, gi2c->cur->len); + gi2c->tx_ph = dma_map_single(tx_dev, dma_buf, msgs[i].len, DMA_TO_DEVICE); + if (dma_mapping_error(tx_dev, gi2c->tx_ph)) { + dev_err(gi2c->se.dev, "dma_map_single for tx failed :%d\n", ret); + i2c_put_dma_safe_msg_buf(dma_buf, &msgs[i], false); + goto geni_i2c_gsi_xfer_out; + } + + peripheral.stretch = stretch; + peripheral.op = I2C_WRITE; + ret = dmaengine_slave_config(gi2c->tx_c, &config); + if (ret) { + dev_err(gi2c->se.dev, "tx dma config error:%d\n", ret); + goto geni_i2c_gsi_xfer_out; + } + peripheral.set_config = false; + peripheral.multi_msg = true; + gi2c->tx_desc = dmaengine_prep_slave_single(gi2c->tx_c, gi2c->tx_ph, msgs[i].len, + DMA_MEM_TO_DEV, + (DMA_PREP_INTERRUPT | DMA_CTRL_ACK)); + if (!gi2c->tx_desc) { + dev_err(gi2c->se.dev, "prep_slave_sg for tx failed\n"); + gi2c->err = -ENOMEM; + goto geni_i2c_err_prep_sg; + } + gi2c->tx_desc->callback_result = i2c_gsi_cb_result; + gi2c->tx_desc->callback_param = gi2c; + + /* Issue TX */ + gi2c->tx_cookie = dmaengine_submit(gi2c->tx_desc); + dma_async_issue_pending(gi2c->tx_c); + + timeout = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); + if (!timeout) { + dev_err(gi2c->se.dev, "I2C timeout gsi flags:%d addr:0x%x\n", + gi2c->cur->flags, gi2c->cur->addr); + gi2c->err = -ETIMEDOUT; + } +geni_i2c_err_prep_sg: + if (gi2c->err) { + dmaengine_terminate_all(gi2c->tx_c); + gi2c->cfg_sent = 0; + } + if (msgs[i].flags & I2C_M_RD) + dma_unmap_single(rx_dev, gi2c->rx_ph, msgs[i].len, DMA_FROM_DEVICE); + else + dma_unmap_single(tx_dev, gi2c->tx_ph, msgs[i].len, DMA_TO_DEVICE); + i2c_put_dma_safe_msg_buf(dma_buf, &msgs[i], !gi2c->err); + if (gi2c->err) + goto geni_i2c_gsi_xfer_out; + } + +geni_i2c_gsi_xfer_out: + if (!ret && gi2c->err) + ret = gi2c->err; + return ret; +} + static int geni_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) @@ -448,6 +646,15 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, } qcom_geni_i2c_conf(gi2c); + + if (gi2c->se_mode == GSI_ONLY) { + ret = geni_i2c_gsi_xfer(adap, msgs, num); + goto geni_i2c_txn_ret; + } else { + /* Don't set shared flag in non-GSI mode */ + gi2c->is_shared = false; + } + for (i = 0; i < num; i++) { u32 m_param = i < (num - 1) ? STOP_STRETCH : 0; @@ -462,6 +669,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, if (ret) break; } +geni_i2c_txn_ret: if (ret == 0) ret = num; @@ -628,7 +836,8 @@ static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev) int ret; struct geni_i2c_dev *gi2c = dev_get_drvdata(dev); - disable_irq(gi2c->irq); + if (gi2c->se_mode == FIFO_SE_DMA) + disable_irq(gi2c->irq); ret = geni_se_resources_off(&gi2c->se); if (ret) { enable_irq(gi2c->irq); @@ -653,8 +862,41 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev) ret = geni_se_resources_on(&gi2c->se); if (ret) return ret; + if (gi2c->se_mode == UNINITIALIZED) { + int proto = geni_se_read_proto(&gi2c->se); + u32 se_mode; + + if (unlikely(proto != GENI_SE_I2C)) { + dev_err(gi2c->se.dev, "Invalid proto %d\n", proto); + geni_se_resources_off(&gi2c->se); + return -ENXIO; + } + + se_mode = readl_relaxed(gi2c->se.base + GENI_IF_DISABLE_RO) & + FIFO_IF_DISABLE; + if (se_mode) { + gi2c->se_mode = GSI_ONLY; + geni_se_select_mode(&gi2c->se, GENI_GPI_DMA); + dev_dbg(gi2c->se.dev, "i2c GSI mode\n"); + } else { + int gi2c_tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se); + + gi2c->se_mode = FIFO_SE_DMA; + gi2c->tx_wm = gi2c_tx_depth - 1; + geni_se_init(&gi2c->se, gi2c->tx_wm, gi2c_tx_depth); + geni_se_config_packing(&gi2c->se, BITS_PER_BYTE, + PACKING_BYTES_PW, true, true, true); + qcom_geni_i2c_conf(gi2c); + dev_dbg(gi2c->se.dev, + "i2c fifo/se-dma mode. fifo depth:%d\n", gi2c_tx_depth); + } + dev_dbg(gi2c->se.dev, "i2c-%d: %s\n", + gi2c->adap.nr, dev_name(gi2c->se.dev)); + } + + if (gi2c->se_mode == FIFO_SE_DMA) + enable_irq(gi2c->irq); - enable_irq(gi2c->irq); gi2c->suspended = 0; return 0; } From patchwork Mon Jan 11 15:16:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 12010975 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD633C4332D for ; Mon, 11 Jan 2021 15:18:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BC7A5229CA for ; Mon, 11 Jan 2021 15:18:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387897AbhAKPSi (ORCPT ); Mon, 11 Jan 2021 10:18:38 -0500 Received: from mail.kernel.org ([198.145.29.99]:54186 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727180AbhAKPSh (ORCPT ); Mon, 11 Jan 2021 10:18:37 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 701B622B30; Mon, 11 Jan 2021 15:17:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1610378276; bh=oPteTSWipDkKpk/yH9fnINrwtd3mWP6TTK/9xr6Tb/I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RDM4+HGrBN6pKYIIKA68wDw7niouvszWFjD1fg74+UnX6bcm/aGSGClxx9jlST6/u Tiebu1ftuv7XSFN2eLW1lnMGiXngzx6YwkO0zX5qBTsEJvAHKG/s8iYuXqn8bfPyny GY/P5hlj8XC5iexuFMNuyI2WhsyQQ4hmVigowqUqKZf1xCYaF5wz31hY+POAuQ1kZd rQl067wUo+UoRcc64HybIr9auJpk0YMqRJmHYkV7Sh+j2Z6Hyzge+YGDq0MQLjMRyZ KJjyjP4i3itKCB9Jw0ws57wfaz7nVXBuwAFad/me1TcpH8UgVa5TRCzq8GHnMfOd9D zT67wUznY4p0Q== From: Vinod Koul To: Bjorn Andersson , Mark Brown , Wolfram Sang Cc: linux-arm-msm@vger.kernel.org, Vinod Koul , Andy Gross , Matthias Kaehlcke , Douglas Anderson , Sumit Semwal , Amit Pundir , linux-spi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 6/7] arm64: dts: qcom: sdm845: Add gpi dma node Date: Mon, 11 Jan 2021 20:46:50 +0530 Message-Id: <20210111151651.1616813-7-vkoul@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210111151651.1616813-1-vkoul@kernel.org> References: <20210111151651.1616813-1-vkoul@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org This add the device node for gpi dma0 instances found in sdm845. Signed-off-by: Vinod Koul --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index bcf888381f14..c9a127bbd606 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1114,6 +1114,29 @@ opp-128000000 { }; }; + gpi_dma0: dma-controller@800000 { + #dma-cells = <3>; + compatible = "qcom,sdm845-gpi-dma"; + reg = <0 0x00800000 0 0x60000>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + ; + dma-channels = <13>; + dma-channel-mask = <0xfa>; + iommus = <&apps_smmu 0x0016 0x0>; + status = "disabled"; + }; + qupv3_id_0: geniqup@8c0000 { compatible = "qcom,geni-se-qup"; reg = <0 0x008c0000 0 0x6000>; @@ -1533,6 +1556,29 @@ uart7: serial@89c000 { }; }; + gpi_dma1: dma-controller@0xa00000 { + #dma-cells = <3>; + compatible = "qcom,sdm845-gpi-dma"; + reg = <0 0x00a00000 0 0x60000>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + ; + dma-channels = <13>; + dma-channel-mask = <0xfa>; + iommus = <&apps_smmu 0x06d6 0x0>; + status = "disabled"; + }; + qupv3_id_1: geniqup@ac0000 { compatible = "qcom,geni-se-qup"; reg = <0 0x00ac0000 0 0x6000>; From patchwork Mon Jan 11 15:16:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 12010977 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A6E1C432C3 for ; Mon, 11 Jan 2021 15:18:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 348CD22A83 for ; Mon, 11 Jan 2021 15:18:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388116AbhAKPSq (ORCPT ); Mon, 11 Jan 2021 10:18:46 -0500 Received: from mail.kernel.org ([198.145.29.99]:54238 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387696AbhAKPSp (ORCPT ); Mon, 11 Jan 2021 10:18:45 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id E671B22795; Mon, 11 Jan 2021 15:17:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1610378284; bh=1k/dDAFiDUWxTSUPTCRsR3hrQeA+upFSBkz9fiRxVQQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pJoA99L7F+nG63Gzc0eukLFTRCbMhaInrZAtZrdKHoRTuZk016tuk6fOKhl6bKhmR quDgj+P2ql+3OrLljdEUsNLZdxDDhQXY8bCpAptXRRvoIuEqfYTRYbRRWwhBzxcoTd HewvUnmhB5CRzAwsl/7hyqF2fghJn+4uuFWyL0earuxwK33V23l0XHavJdcSsrcrYf lS39IeFA/YfEqKuBLXTwC8JIE6uqv0R55FE6OtL85V7xVM25xOGbzzLXij4Gwzd/y3 wJWvQl3ngiD9zT1vmiGmUMYeloGNwt7OVLFtZHpRE3oNeZ+MtNmBgrOHStN1t7nhnv CpMI0HlSfAiag== From: Vinod Koul To: Bjorn Andersson , Mark Brown , Wolfram Sang Cc: linux-arm-msm@vger.kernel.org, Vinod Koul , Andy Gross , Matthias Kaehlcke , Douglas Anderson , Sumit Semwal , Amit Pundir , linux-spi@vger.kernel.org, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 7/7] arm64: dts: qcom: sdm845: enable dma for spi Date: Mon, 11 Jan 2021 20:46:51 +0530 Message-Id: <20210111151651.1616813-8-vkoul@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210111151651.1616813-1-vkoul@kernel.org> References: <20210111151651.1616813-1-vkoul@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org Add dmas property for spi@880000 and pinconf setting so that we can use dma for this spi device. Also, add iommu properties for qup and spi. Signed-off-by: Vinod Koul --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 ++++ arch/arm64/boot/dts/qcom/sdm845.dtsi | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index 7cc236575ee2..0653468f26ce 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -418,6 +418,10 @@ &gcc { ; }; +&gpi_dma0 { + status = "okay"; +}; + &gpu { zap-shader { memory-region = <&gpu_mem>; diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index c9a127bbd606..bd9952f54721 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1183,6 +1184,9 @@ spi0: spi@880000 { interconnects = <&aggre1_noc MASTER_QUP_1 0 &config_noc SLAVE_BLSP_1 0>, <&gladiator_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_BLSP_1 0>; interconnect-names = "qup-core", "qup-config"; + dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>, + <&gpi_dma0 1 0 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -2622,6 +2626,13 @@ pinmux { "gpio2", "gpio3"; function = "qup0"; }; + + config { + pins = "gpio0", "gpio1", + "gpio2", "gpio3"; + drive-strength = <6>; + bias-disable; + }; }; qup_spi1_default: qup-spi1-default {