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: 360789 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: 360478 Delivered-To: patch@linaro.org Received: by 2002:a02:85a7:0:0:0:0:0 with SMTP id d36csp2968222jai; Mon, 11 Jan 2021 07:19:13 -0800 (PST) X-Google-Smtp-Source: ABdhPJzE75/MrudoA1Fg7RI3ufMHicUhlLZwejZiI+gd9LJZsZU4soJcej9+4LY6zydmMKuibWfm X-Received: by 2002:a17:907:447d:: with SMTP id oo21mr11098135ejb.367.1610378353529; Mon, 11 Jan 2021 07:19:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1610378353; cv=none; d=google.com; s=arc-20160816; b=GEiR6bMTbVJ6KoL+9XGfs+yRYO5HKZ/fv0T2H3dyN7zLMHiLOZOhvuXCu7A0ijnF+m Mb5ltxGAEwgq4Lk0LJSs9rcV7dk7UXQtyBO1xIimZtTVBFKJg+OeYopu39JWLqbkW300 A95SBdfFnCAMHKyGtvhyTLqsSO44QfsmD7khOOk0cAlPxYRi/CbMoBqAMZFQCmGWj96j vkYXkN6UYuvbDfkAD3ejkHL8au1l9zie6SERhzKW5HhSAWrs5VQQ1a8OIx9hkw4LpkFk yUPJUkjXggs45Ow1kDb7ppA00ZfTFcZuH4iTqtgbbwwGiiAXKA0Wbf310g3zo/U9FVHf laOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=0V6uyVTwO598D2L7cYaj4WGUXc4zwpYlZvra4s76HzI=; b=mH0YwHUkFhhF19tfhHnGqLuUNdcqvcHCK+stsRt92LEnDvXPBfzMDCSVkjVxzFWRis hANAhYzBGvUoY+3jh8E4U38CLlusJ14yStP7K70xFBdFCaw7avqt9BDI4UgRIgzdxvOu kOcV4ul6rvR7qBEPo9LWKnI1GKl/YXpMYPM0aPZLHY66mJ9sn84j4CxKpoL/3RK6EhVo u42XCVRgKzQJxSCnGAjPsmL6QiPRaGuVKZkoFCZrNqhGg9jo1gR0iO0mqm/i11Grmt/l JwlvbFBdAPVsX+hlSPFMfM3nx7z6plRpfq9TFz84KhFaJpn4euP8mmCOwZ/tizu7IuEk 976g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=gUo4RjYU; spf=pass (google.com: domain of linux-spi-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-spi-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t21si6596995ejf.648.2021.01.11.07.19.13; Mon, 11 Jan 2021 07:19:13 -0800 (PST) Received-SPF: pass (google.com: domain of linux-spi-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=gUo4RjYU; spf=pass (google.com: domain of linux-spi-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-spi-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733022AbhAKPSQ (ORCPT + 1 other); 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(-) -- 2.26.2 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: 360788 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: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: 360787 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>;