From patchwork Fri Dec 15 11:47:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thangaraj Samynathan X-Patchwork-Id: 179213 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:3b04:b0:fb:cd0c:d3e with SMTP id c4csp9211379dys; Fri, 15 Dec 2023 03:51:39 -0800 (PST) X-Google-Smtp-Source: AGHT+IFyAQkc5f3qV18d2q4L3fXd32J6zJfV4N4lihiCUx3q7BaWm0KVRfbNS8cM1URxGGpIBrUd X-Received: by 2002:a17:907:9708:b0:a1d:9831:1da with SMTP id jg8-20020a170907970800b00a1d983101damr7474321ejc.91.1702641099570; Fri, 15 Dec 2023 03:51:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1702641099; cv=none; d=google.com; s=arc-20160816; b=kSIEZVGTiU127bW/e5gbg9gnKJZ4wGpkLCzShlUWm7snJrVg/Q7KXU7FtOak03d2vS vP1Glg1Ilvq0epHImIIrQN6sPRIoprEIQhH6BIAYOvF5wLxSReIk4gBBzUn79zy71lqr VZwkcYrGzqRJpL6Q9HPKHFZ7+fZo67ytiiMZGbtvxTak87MyLa+FEWNcrWRfggvphxGa zNMlMQCU7aK7SD2ux4aa9KQfj6wD0Fgg1ObUcatMYKp1uuIEeuAJ+SPL0PGQhb9oEaNG msIkXoSyrlNjC2NGmPQPWRDK0vVrxYKwzTTiVe/t/mcau4LAbaJ8iPmmZjwUPzRdGTJ3 Amvw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=i3P02RSqyKJ1LGpPvSud6sf7ziXsa40InRkeNAr4Gp8=; fh=cGbkLwFjdUmwzsSfH4uGElh042qw4yrimp50Fdi/yLk=; b=FZ4oOkNNlOtT7dCWoXZqreo176ugZmx7q53BrI8GREEw/+X+7NMPdqIkE2K+Z1e9VF KKxWNqJFDgQtNxcouUwAUqkjMuV7VLkLFSCbHEljmxer1cPH5iS9t/HkXdB3uxZKtw6g o7Ur7HAK7lsahJeAjetZypeWQyKKMTGVMLR3U/PME/g36WV7ZrV150hgci/ioMB0hVZz Ouw5JJxjrpgEps1/mQdKu1M+yQrOBpmEEw8X6FFKNWS37xlV6CqfBrR1yFaguOGUUuy9 mkBluAD87DsEE/V+mKW0k804b2ogDmXFw73TSM5L/7//OqH2mnblTqUps0pIqEfcA2Z6 1Aiw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@microchip.com header.s=mchp header.b=hlWVnDA6; spf=pass (google.com: domain of linux-kernel+bounces-871-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-871-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=REJECT dis=NONE) header.from=microchip.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id j14-20020a170906050e00b00a1fb2be9d79si797976eja.1011.2023.12.15.03.51.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Dec 2023 03:51:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-871-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@microchip.com header.s=mchp header.b=hlWVnDA6; spf=pass (google.com: domain of linux-kernel+bounces-871-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-871-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=REJECT dis=NONE) header.from=microchip.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 0BBBA1F225C9 for ; Fri, 15 Dec 2023 11:51:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 434C42D7AF; Fri, 15 Dec 2023 11:50:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="hlWVnDA6" X-Original-To: linux-kernel@vger.kernel.org Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2AC232556B; Fri, 15 Dec 2023 11:50:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=microchip.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=microchip.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1702641029; x=1734177029; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+c81t6P+VrINi52C/mrkf7kTMz9CCpU+nj9sKXqCplI=; b=hlWVnDA67ouRf7ETxRCJZ2wnIQoMPbzgIoK/CjYa4ZincobVA4YKemCI Me8phZapwCqB/G/j46xN4zfDYimbMmrq+Tmqf+hBth8ztdje2/kJM15qA oJ7EqtzPSDEd5FXS5CUatS/MqMDnJiPjsCLdyz+V1RtvgQW9IWNNcico4 y5mtW/biaYqC3/e8rdR+x9iFEk5biR95n2nA+eDvF6NxdUpvquIBClB13 tmH+8LnQAYn/42TYa1R+y9+6BHiUMsn/5tyrL7SsucS3kkKE3b/WzM/0M /Ze+Yg7Vl1I8ePnBdeqicrHIx3X5nfCUq1mv8VAlhEAhBdRP+X7rUIb6I g==; X-CSE-ConnectionGUID: LGva2yzVSgmRfFnu4BtIaw== X-CSE-MsgGUID: +5RO2q1pS+ydHvkV8he07w== X-ThreatScanner-Verdict: Negative X-IronPort-AV: E=Sophos;i="6.04,278,1695711600"; d="scan'208";a="14317231" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa1.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 15 Dec 2023 04:50:20 -0700 Received: from chn-vm-ex03.mchp-main.com (10.10.85.151) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Fri, 15 Dec 2023 04:50:14 -0700 Received: from che-dk-ungapp03lx.microchip.com (10.10.85.11) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Fri, 15 Dec 2023 04:50:11 -0700 From: Thangaraj Samynathan To: CC: , , , , , , Subject: [PATCH SPI for-next 3/3] spi: mchp-pci1xxxx: DMA Write Support for copying data from SPI Buf Date: Fri, 15 Dec 2023 17:17:48 +0530 Message-ID: <20231215114748.152319-4-thangaraj.s@microchip.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231215114748.152319-1-thangaraj.s@microchip.com> References: <20231215114748.152319-1-thangaraj.s@microchip.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1785348593509677845 X-GMAIL-MSGID: 1785348593509677845 DMA Write setup is done in pci1xxxx_spi_transfer_with_dma, before initiating the transaction. Once the SPI transaction complete interrupt is received, doorbell is written to initiate DMA Write. DMA Write operation copies the data from SPI RX buffer to CPU buffer. Signed-off-by: Thangaraj Samynathan --- drivers/spi/spi-pci1xxxx.c | 93 +++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index 824885ada9b6..5dcb63c367b9 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -57,8 +57,13 @@ /* DMA Related Registers */ #define SPI_DMA_ADDR_BASE (0x1000) #define SPI_DMA_GLOBAL_WR_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x0C) +#define SPI_DMA_WR_DOORBELL_REG (SPI_DMA_ADDR_BASE + 0x10) #define SPI_DMA_GLOBAL_RD_ENGINE_EN (SPI_DMA_ADDR_BASE + 0x2C) #define SPI_DMA_RD_DOORBELL_REG (SPI_DMA_ADDR_BASE + 0x30) +#define SPI_DMA_INTR_WR_STS (SPI_DMA_ADDR_BASE + 0x4C) +#define SPI_DMA_WR_INT_MASK (SPI_DMA_ADDR_BASE + 0x54) +#define SPI_DMA_INTR_WR_CLR (SPI_DMA_ADDR_BASE + 0x58) +#define SPI_DMA_ERR_WR_STS (SPI_DMA_ADDR_BASE + 0x5C) #define SPI_DMA_INTR_IMWR_WDONE_LOW (SPI_DMA_ADDR_BASE + 0x60) #define SPI_DMA_INTR_IMWR_WDONE_HIGH (SPI_DMA_ADDR_BASE + 0x64) #define SPI_DMA_INTR_IMWR_WABORT_LOW (SPI_DMA_ADDR_BASE + 0x68) @@ -74,7 +79,9 @@ #define SPI_DMA_INTR_IMWR_RABORT_HIGH (SPI_DMA_ADDR_BASE + 0xD8) #define SPI_DMA_INTR_RD_IMWR_DATA (SPI_DMA_ADDR_BASE + 0xDC) +#define SPI_DMA_CH0_WR_BASE (SPI_DMA_ADDR_BASE + 0x200) #define SPI_DMA_CH0_RD_BASE (SPI_DMA_ADDR_BASE + 0x300) +#define SPI_DMA_CH1_WR_BASE (SPI_DMA_ADDR_BASE + 0x400) #define SPI_DMA_CH1_RD_BASE (SPI_DMA_ADDR_BASE + 0x500) #define SPI_DMA_CH_CTL1_OFFSET (0x00) @@ -126,7 +133,9 @@ struct pci1xxxx_spi_internal { u8 hw_inst; bool spi_xfer_in_progress; + void *rx_buf; bool dma_aborted_rd; + bool dma_aborted_wr; int irq; struct completion spi_xfer_done; struct spi_controller *spi_host; @@ -333,6 +342,26 @@ static void pci1xxxx_spi_setup_dma_read(struct pci1xxxx_spi_internal *p, base + SPI_DMA_CH_DAR_HI_OFFSET); } +static void pci1xxxx_spi_setup_dma_write(struct pci1xxxx_spi_internal *p, + dma_addr_t dma_addr, u32 len) +{ + void *base; + + if (!p->hw_inst) + base = p->parent->dma_offset_bar + SPI_DMA_CH0_WR_BASE; + else + base = p->parent->dma_offset_bar + SPI_DMA_CH1_WR_BASE; + + writel(DMA_INTR_EN, base + SPI_DMA_CH_CTL1_OFFSET); + writel(len, base + SPI_DMA_CH_XFER_LEN_OFFSET); + writel(lower_32_bits(dma_addr), base + SPI_DMA_CH_DAR_LO_OFFSET); + writel(upper_32_bits(dma_addr), base + SPI_DMA_CH_DAR_HI_OFFSET); + writel(lower_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_RSP_BUF_OFFSET(p->hw_inst)), + base + SPI_DMA_CH_SAR_LO_OFFSET); + writel(upper_32_bits(SPI_PERI_ADDR_BASE + SPI_MST_RSP_BUF_OFFSET(p->hw_inst)), + base + SPI_DMA_CH_SAR_HI_OFFSET); +} + static void pci1xxxx_spi_setup(struct pci1xxxx_spi *par, u8 hw_inst, u32 mode, u8 clkdiv, u32 len) { @@ -427,9 +456,9 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr, struct pci1xxxx_spi_internal *p = spi_controller_get_devdata(spi_ctlr); struct pci1xxxx_spi *par = p->parent; struct device *dev = &par->dev->dev; + dma_addr_t rx_dma_addr = 0; dma_addr_t tx_dma_addr = 0; u64 bytes_transfered = 0; - u64 bytes_recvd = 0; int loop_count; int ret = 0; u32 regval; @@ -439,6 +468,7 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr, u32 i; p->spi_xfer_in_progress = true; + p->rx_buf = xfer->rx_buf; clkdiv = pci1xxxx_get_clock_div(xfer->speed_hz); rx_buf = xfer->rx_buf; regval = readl(par->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); @@ -456,6 +486,15 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr, goto error; } + if (xfer->rx_buf) { + rx_dma_addr = dma_map_single(dev, (void *)xfer->rx_buf, xfer->len, DMA_FROM_DEVICE); + if (dma_mapping_error(NULL, rx_dma_addr)) { + rx_dma_addr = 0; + ret = -ENOMEM; + goto error; + } + } + loop_count = DIV_ROUND_UP(xfer->len, SPI_MAX_DATA_LEN); len = SPI_MAX_DATA_LEN; pci1xxxx_spi_setup(par, p->hw_inst, spi->mode, clkdiv, len); @@ -466,6 +505,8 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr, } pci1xxxx_spi_setup_dma_read(p, (tx_dma_addr + bytes_transfered), len); + if (rx_dma_addr) + pci1xxxx_spi_setup_dma_write(p, (rx_dma_addr + bytes_transfered), len); writel(p->hw_inst, par->dma_offset_bar + SPI_DMA_RD_DOORBELL_REG); @@ -495,14 +536,31 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr, p->dma_aborted_rd = false; ret = -ECANCELED; } + if (p->dma_aborted_wr) { + writel(SPI_DMA_ENGINE_DIS, + par->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN); + + /* + * DMA ENGINE reset takes time if any TLP + * completeion in progress, should wait + * till DMA Engine reset is completed. + */ + ret = readl_poll_timeout(par->dma_offset_bar + + SPI_DMA_GLOBAL_WR_ENGINE_EN, regval, + (regval == 0x0), 0, USEC_PER_MSEC); + if (ret) { + ret = -ECANCELED; + goto error; + } + + writel(SPI_DMA_ENGINE_EN, + par->dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN); + p->dma_aborted_wr = false; + ret = -ECANCELED; + } goto error; } bytes_transfered += len; - if (rx_buf) { - memcpy_fromio(&rx_buf[bytes_recvd], par->reg_base + - SPI_MST_RSP_BUF_OFFSET(p->hw_inst), len); - bytes_recvd += len; - } ret = 0; } @@ -510,6 +568,8 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr, p->spi_xfer_in_progress = false; if (tx_dma_addr) dma_unmap_single(dev, tx_dma_addr, xfer->len, DMA_TO_DEVICE); + if (rx_dma_addr) + dma_unmap_single(dev, rx_dma_addr, xfer->len, DMA_FROM_DEVICE); return ret; } @@ -525,7 +585,11 @@ static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev) regval = readl(p->parent->reg_base + SPI_MST_EVENT_REG_OFFSET(p->hw_inst)); if (regval & SPI_INTR) { /* Clear xfer_done */ - complete(&p->spi_xfer_done); + if (p->parent->can_dma && p->rx_buf) + writel(p->hw_inst, p->parent->dma_offset_bar + + SPI_DMA_WR_DOORBELL_REG); + else + complete(&p->parent->spi_int[p->hw_inst]->spi_xfer_done); spi_int_fired = IRQ_HANDLED; } @@ -549,6 +613,21 @@ static irqreturn_t pci1xxxx_spi_isr(int irq, void *dev) spi_int_fired = IRQ_HANDLED; } writel(regval, p->parent->dma_offset_bar + SPI_DMA_INTR_RD_CLR); + + /* Clear the DMA WR INT */ + regval = readl(p->parent->dma_offset_bar + SPI_DMA_INTR_WR_STS); + if (regval & SPI_DMA_DONE_INT_MASK) { + if (regval & SPI_DMA_CH0_DONE_INT) + complete(&p->parent->spi_int[SPI0]->spi_xfer_done); + if (regval & SPI_DMA_CH1_DONE_INT) + complete(&p->parent->spi_int[SPI1]->spi_xfer_done); + spi_int_fired = IRQ_HANDLED; + } + if (regval & SPI_DMA_ABORT_INT_MASK) { + p->dma_aborted_wr = true; + spi_int_fired = IRQ_HANDLED; + } + writel(regval, p->parent->dma_offset_bar + SPI_DMA_INTR_WR_CLR); spin_unlock_irqrestore(&p->parent->dma_reg_lock, flags); return spi_int_fired;