From mboxrd@z Thu Jan 1 00:00:00 1970 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=-9.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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 C29FAC43457 for ; Mon, 19 Oct 2020 08:21:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7942B22276 for ; Mon, 19 Oct 2020 08:21:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728923AbgJSIVh (ORCPT ); Mon, 19 Oct 2020 04:21:37 -0400 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:46773 "EHLO out4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728781AbgJSIVg (ORCPT ); Mon, 19 Oct 2020 04:21:36 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 8C4FB5C00A5; Mon, 19 Oct 2020 04:21:34 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Mon, 19 Oct 2020 04:21:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cerno.tech; h= date:from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm1; bh=XTmgxObblxDSzINzf+hlaODgpg+ rdkjKpiOLWaGp4ho=; b=OazQWh6fObFP81S9ZwenHPQ3PGSboiLsslkHHbIaMcS +Mctv4hPBRwI6cJgjvMEH9lAkQB+DSNHeR2xSHaw7r+ZlyGLH7kZouyzICuHaEW0 ul9bu48hs2KG/rWG8qsN4Wfg6Ybq0yIatNtuJFwf9cHlJ9qWooH4tK3i/B7vMyZi bQKn0tZJTjTD8Y6M3MVKP6sI1wxyEjsSH/1QfMER3SYKmcFcHeCjAOfv/GBD8vdb BcKB9Q/o7mUS8muMl3TaOwRvRzgvwbWkN5KOOypnmZHUKQTAgvOWx/26Ld9GwWVk sUTodU1s9+mZzkUz3hJupM4Z25fjXtS9viRFQSN70ZQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=XTmgxO bblxDSzINzf+hlaODgpg+rdkjKpiOLWaGp4ho=; b=SxVLs6tbh3QJ0PgccNxM2A ZOqHufVA8N/aF4ZL279cxFVYZmFzF+PCFq/LyLM5MKN3QTcOkx6p2Lv1qXzirVZZ o9ObioV3NZJ86sZF1np4CYtpEJvPZW0JMpOKxHrhbMNlTRDrD4o9OFqfbfKDSXIa x6QRllv07NB7tozjuoBwepZa1SZEyQ30TS9dPH2xLh2nrStfL38FPXtGKTp12H2S DXWy0oZi8m1eO9FjUDXrlo4/C1hsHosxH1wENE6rbDg/Xr/OQo7w7LxrdbVegH3a /iXP8q6OhOvgS5FJQ18NpwDYCtaOP6DFnoPc/TWKrvKbvUPwlF1wj3LrJtUVBhlQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrjedugddtgecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomhepofgrgihimhgv ucftihhprghrugcuoehmrgigihhmvgestggvrhhnohdrthgvtghhqeenucggtffrrghtth gvrhhnpeffuedugfdvjeeihedvgefhieeikeelteehteekffetudeiueeggfduueevffet geenucffohhmrghinhepphhinhgvieegrdhorhhgnecukfhppeeltddrkeelrdeikedrje einecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepmhgr gihimhgvsegtvghrnhhordhtvggthh X-ME-Proxy: Received: from localhost (lfbn-tou-1-1502-76.w90-89.abo.wanadoo.fr [90.89.68.76]) by mail.messagingengine.com (Postfix) with ESMTPA id 3BB89328005A; Mon, 19 Oct 2020 04:21:31 -0400 (EDT) Date: Mon, 19 Oct 2020 10:21:29 +0200 From: Maxime Ripard To: Alexander Kochetkov Cc: Mark Brown , Chen-Yu Tsai , linux-spi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH] spi: spi-sun6i: implement DMA-based transfer mode Message-ID: <20201019082129.myxpxla5xwoqwldo@gilmour.lan> References: <20201015154740.20825-1-al.kochet@gmail.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="qboiznam3rkxrap6" Content-Disposition: inline In-Reply-To: <20201015154740.20825-1-al.kochet@gmail.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --qboiznam3rkxrap6 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi! On Thu, Oct 15, 2020 at 06:47:40PM +0300, Alexander Kochetkov wrote: > DMA-based transfer will be enabled if data length is larger than FIFO size > (64 bytes for A64). This greatly reduce number of interrupts for > transferring data. >=20 > For smaller data size PIO mode will be used. In PIO mode whole buffer will > be loaded into FIFO. >=20 > If driver failed to request DMA channels then it fallback for PIO mode. >=20 > Tested on SOPINE (https://www.pine64.org/sopine/) >=20 > Signed-off-by: Alexander Kochetkov Thanks for working on this, it's been a bit overdue > --- > drivers/spi/spi-sun6i.c | 171 +++++++++++++++++++++++++++++++++++++--- > 1 file changed, 159 insertions(+), 12 deletions(-) >=20 > diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c > index 19238e1b76b4..38e5b8af7da6 100644 > --- a/drivers/spi/spi-sun6i.c > +++ b/drivers/spi/spi-sun6i.c > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > =20 > #include > =20 > @@ -52,10 +53,12 @@ > =20 > #define SUN6I_FIFO_CTL_REG 0x18 > #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK 0xff > +#define SUN6I_FIFO_CTL_RF_DRQ_EN BIT(8) > #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS 0 > #define SUN6I_FIFO_CTL_RF_RST BIT(15) > #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK 0xff > #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS 16 > +#define SUN6I_FIFO_CTL_TF_DRQ_EN BIT(24) > #define SUN6I_FIFO_CTL_TF_RST BIT(31) > =20 > #define SUN6I_FIFO_STA_REG 0x1c > @@ -83,6 +86,8 @@ > struct sun6i_spi { > struct spi_master *master; > void __iomem *base_addr; > + dma_addr_t dma_addr_rx; > + dma_addr_t dma_addr_tx; > struct clk *hclk; > struct clk *mclk; > struct reset_control *rstc; > @@ -92,6 +97,7 @@ struct sun6i_spi { > const u8 *tx_buf; > u8 *rx_buf; > int len; > + bool use_dma; > unsigned long fifo_depth; > }; > =20 > @@ -182,6 +188,66 @@ static size_t sun6i_spi_max_transfer_size(struct spi= _device *spi) > return SUN6I_MAX_XFER_SIZE - 1; > } > =20 > +static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi, > + struct spi_transfer *tfr) > +{ > + struct dma_async_tx_descriptor *rxdesc, *txdesc; > + struct spi_master *master =3D sspi->master; > + > + rxdesc =3D NULL; > + if (tfr->rx_buf) { > + struct dma_slave_config rxconf =3D { > + .direction =3D DMA_DEV_TO_MEM, > + .src_addr =3D sspi->dma_addr_rx, > + .src_addr_width =3D 1, > + .src_maxburst =3D 1, > + }; That doesn't really look optimal, the controller seems to be able to read / write 32 bits at a time from its FIFO and we probably can increase the burst length too? > + > + dmaengine_slave_config(master->dma_rx, &rxconf); > + > + rxdesc =3D dmaengine_prep_slave_sg( > + master->dma_rx, > + tfr->rx_sg.sgl, tfr->rx_sg.nents, > + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); checkpatch --strict complains about this one (your line shouldn't end with a parenthesis). > + if (!rxdesc) > + return -EINVAL; > + } > + > + txdesc =3D NULL; > + if (tfr->tx_buf) { > + struct dma_slave_config txconf =3D { > + .direction =3D DMA_MEM_TO_DEV, > + .dst_addr =3D sspi->dma_addr_tx, > + .dst_addr_width =3D 1, > + .dst_maxburst =3D 1, > + }; > + > + dmaengine_slave_config(master->dma_tx, &txconf); > + > + txdesc =3D dmaengine_prep_slave_sg( > + master->dma_tx, > + tfr->tx_sg.sgl, tfr->tx_sg.nents, > + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); > + if (!txdesc) { > + if (rxdesc) > + dmaengine_terminate_sync(master->dma_rx); > + return -EINVAL; > + } > + } > + > + if (tfr->rx_buf) { > + dmaengine_submit(rxdesc); > + dma_async_issue_pending(master->dma_rx); > + } > + > + if (tfr->tx_buf) { > + dmaengine_submit(txdesc); > + dma_async_issue_pending(master->dma_tx); > + } > + > + return 0; > +} > + > static int sun6i_spi_transfer_one(struct spi_master *master, > struct spi_device *spi, > struct spi_transfer *tfr) > @@ -201,6 +267,8 @@ static int sun6i_spi_transfer_one(struct spi_master *= master, > sspi->tx_buf =3D tfr->tx_buf; > sspi->rx_buf =3D tfr->rx_buf; > sspi->len =3D tfr->len; > + sspi->use_dma =3D master->can_dma ? > + master->can_dma(master, spi, tfr) : false; > =20 > /* Clear pending interrupts */ > sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0); > @@ -216,9 +284,17 @@ static int sun6i_spi_transfer_one(struct spi_master = *master, > * (See spi-sun4i.c) > */ > trig_level =3D sspi->fifo_depth / 4 * 3; > - sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, > - (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) | > - (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS)); > + reg =3D (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) | > + (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS); > + > + if (sspi->use_dma) { > + if (tfr->tx_buf) > + reg |=3D SUN6I_FIFO_CTL_TF_DRQ_EN; > + if (tfr->rx_buf) > + reg |=3D SUN6I_FIFO_CTL_RF_DRQ_EN; > + } > + > + sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, reg); > =20 > /* > * Setup the transfer control register: Chip Select, > @@ -300,16 +376,28 @@ static int sun6i_spi_transfer_one(struct spi_master= *master, > sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len); > sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len); > =20 > - /* Fill the TX FIFO */ > - sun6i_spi_fill_fifo(sspi); > + if (!sspi->use_dma) { > + /* Fill the TX FIFO */ > + sun6i_spi_fill_fifo(sspi); > + } else { > + ret =3D sun6i_spi_prepare_dma(sspi, tfr); > + if (ret) { > + dev_warn(&master->dev, > + "%s: prepare DMA failed, ret=3D%d", > + dev_name(&spi->dev), ret); > + return ret; > + } > + } > =20 > /* Enable the interrupts */ > reg =3D SUN6I_INT_CTL_TC; > =20 > - if (rx_len > sspi->fifo_depth) > - reg |=3D SUN6I_INT_CTL_RF_RDY; > - if (tx_len > sspi->fifo_depth) > - reg |=3D SUN6I_INT_CTL_TF_ERQ; > + if (!sspi->use_dma) { > + if (rx_len > sspi->fifo_depth) > + reg |=3D SUN6I_INT_CTL_RF_RDY; > + if (tx_len > sspi->fifo_depth) > + reg |=3D SUN6I_INT_CTL_TF_ERQ; > + } > =20 > sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg); > =20 > @@ -332,6 +420,11 @@ static int sun6i_spi_transfer_one(struct spi_master = *master, > =20 > sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0); > =20 > + if (ret && sspi->use_dma) { > + dmaengine_terminate_sync(master->dma_rx); > + dmaengine_terminate_sync(master->dma_tx); > + } > + > return ret; > } > =20 > @@ -343,7 +436,8 @@ static irqreturn_t sun6i_spi_handler(int irq, void *d= ev_id) > /* Transfer complete */ > if (status & SUN6I_INT_CTL_TC) { > sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC); > - sun6i_spi_drain_fifo(sspi); > + if (!sspi->use_dma) > + sun6i_spi_drain_fifo(sspi); Is it causing any issue? The FIFO will be drained only if there's something remaining in the FIFO, which shouldn't happen with DMA? Maxime --qboiznam3rkxrap6 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCX41MiQAKCRDj7w1vZxhR xURAAQD2D/f4gllUD42fAjpjkz5DH/BOU3aL8doWmHSnE2PF8QEAscqzE9DFSfI/ Onc8zzd+eSxCXsLif90Bx7puB6Ifugg= =lObj -----END PGP SIGNATURE----- --qboiznam3rkxrap6-- From mboxrd@z Thu Jan 1 00:00:00 1970 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=-9.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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 CA287C433E7 for ; Mon, 19 Oct 2020 08:23:22 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3B20B2224D for ; Mon, 19 Oct 2020 08:23:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="VxPTsJiR"; dkim=temperror (0-bit key) header.d=cerno.tech header.i=@cerno.tech header.b="OazQWh6f"; dkim=temperror (0-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="SxVLs6tb" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3B20B2224D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=cerno.tech Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Type:Cc: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: In-Reply-To:MIME-Version:References:Message-ID:Subject:To:From:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=M4izDTiDnahStyN2XDpXDS+OJSNutuNebrT01pdtwlo=; b=VxPTsJiRXFGw2GE2v3GRF93r+ DOEc+NnjXXFetriFUDQlAvsnGo0VnijP0ufLI+lWVAmEKZaYUWbE7QK1iZxMbgoat58DMpSe+XlWg FYB56THV82FFi6l0CkpRKzI/9NU4xQQB31aD9z4KZue8qZ69WCtJyqtKxVCWMy2d4CsCBRXPwh5lQ fK2ajf3UGSFoqJVNl/EsxEZLBSt5J4vLGmKSmb9xhqqzZCLIjaxRqE4TqgTU7NTsxmJTlS4q/wX+1 WRKJNteQiyqBOOgavYN+gAuUY2rxknGO/Scavvtu7MOBtXn8hHE7/BdicC7gFlQcMqenOc6LZ/IA5 dSbBfvqbQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kUQQG-0001cm-22; Mon, 19 Oct 2020 08:21:40 +0000 Received: from out4-smtp.messagingengine.com ([66.111.4.28]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kUQQC-0001c8-0a for linux-arm-kernel@lists.infradead.org; Mon, 19 Oct 2020 08:21:37 +0000 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 8C4FB5C00A5; Mon, 19 Oct 2020 04:21:34 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Mon, 19 Oct 2020 04:21:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cerno.tech; h= date:from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm1; bh=XTmgxObblxDSzINzf+hlaODgpg+ rdkjKpiOLWaGp4ho=; b=OazQWh6fObFP81S9ZwenHPQ3PGSboiLsslkHHbIaMcS +Mctv4hPBRwI6cJgjvMEH9lAkQB+DSNHeR2xSHaw7r+ZlyGLH7kZouyzICuHaEW0 ul9bu48hs2KG/rWG8qsN4Wfg6Ybq0yIatNtuJFwf9cHlJ9qWooH4tK3i/B7vMyZi bQKn0tZJTjTD8Y6M3MVKP6sI1wxyEjsSH/1QfMER3SYKmcFcHeCjAOfv/GBD8vdb BcKB9Q/o7mUS8muMl3TaOwRvRzgvwbWkN5KOOypnmZHUKQTAgvOWx/26Ld9GwWVk sUTodU1s9+mZzkUz3hJupM4Z25fjXtS9viRFQSN70ZQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=XTmgxO bblxDSzINzf+hlaODgpg+rdkjKpiOLWaGp4ho=; b=SxVLs6tbh3QJ0PgccNxM2A ZOqHufVA8N/aF4ZL279cxFVYZmFzF+PCFq/LyLM5MKN3QTcOkx6p2Lv1qXzirVZZ o9ObioV3NZJ86sZF1np4CYtpEJvPZW0JMpOKxHrhbMNlTRDrD4o9OFqfbfKDSXIa x6QRllv07NB7tozjuoBwepZa1SZEyQ30TS9dPH2xLh2nrStfL38FPXtGKTp12H2S DXWy0oZi8m1eO9FjUDXrlo4/C1hsHosxH1wENE6rbDg/Xr/OQo7w7LxrdbVegH3a /iXP8q6OhOvgS5FJQ18NpwDYCtaOP6DFnoPc/TWKrvKbvUPwlF1wj3LrJtUVBhlQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrjedugddtgecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvuffkfhggtggujgesghdtreertddtvdenucfhrhhomhepofgrgihimhgv ucftihhprghrugcuoehmrgigihhmvgestggvrhhnohdrthgvtghhqeenucggtffrrghtth gvrhhnpeffuedugfdvjeeihedvgefhieeikeelteehteekffetudeiueeggfduueevffet geenucffohhmrghinhepphhinhgvieegrdhorhhgnecukfhppeeltddrkeelrdeikedrje einecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepmhgr gihimhgvsegtvghrnhhordhtvggthh X-ME-Proxy: Received: from localhost (lfbn-tou-1-1502-76.w90-89.abo.wanadoo.fr [90.89.68.76]) by mail.messagingengine.com (Postfix) with ESMTPA id 3BB89328005A; Mon, 19 Oct 2020 04:21:31 -0400 (EDT) Date: Mon, 19 Oct 2020 10:21:29 +0200 From: Maxime Ripard To: Alexander Kochetkov Subject: Re: [PATCH] spi: spi-sun6i: implement DMA-based transfer mode Message-ID: <20201019082129.myxpxla5xwoqwldo@gilmour.lan> References: <20201015154740.20825-1-al.kochet@gmail.com> MIME-Version: 1.0 In-Reply-To: <20201015154740.20825-1-al.kochet@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201019_042136_640255_FE827BB5 X-CRM114-Status: GOOD ( 29.30 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Chen-Yu Tsai , Mark Brown , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org Content-Type: multipart/mixed; boundary="===============7206180444206808083==" Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org --===============7206180444206808083== Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="qboiznam3rkxrap6" Content-Disposition: inline --qboiznam3rkxrap6 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi! On Thu, Oct 15, 2020 at 06:47:40PM +0300, Alexander Kochetkov wrote: > DMA-based transfer will be enabled if data length is larger than FIFO size > (64 bytes for A64). This greatly reduce number of interrupts for > transferring data. >=20 > For smaller data size PIO mode will be used. In PIO mode whole buffer will > be loaded into FIFO. >=20 > If driver failed to request DMA channels then it fallback for PIO mode. >=20 > Tested on SOPINE (https://www.pine64.org/sopine/) >=20 > Signed-off-by: Alexander Kochetkov Thanks for working on this, it's been a bit overdue > --- > drivers/spi/spi-sun6i.c | 171 +++++++++++++++++++++++++++++++++++++--- > 1 file changed, 159 insertions(+), 12 deletions(-) >=20 > diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c > index 19238e1b76b4..38e5b8af7da6 100644 > --- a/drivers/spi/spi-sun6i.c > +++ b/drivers/spi/spi-sun6i.c > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > =20 > #include > =20 > @@ -52,10 +53,12 @@ > =20 > #define SUN6I_FIFO_CTL_REG 0x18 > #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK 0xff > +#define SUN6I_FIFO_CTL_RF_DRQ_EN BIT(8) > #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS 0 > #define SUN6I_FIFO_CTL_RF_RST BIT(15) > #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK 0xff > #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS 16 > +#define SUN6I_FIFO_CTL_TF_DRQ_EN BIT(24) > #define SUN6I_FIFO_CTL_TF_RST BIT(31) > =20 > #define SUN6I_FIFO_STA_REG 0x1c > @@ -83,6 +86,8 @@ > struct sun6i_spi { > struct spi_master *master; > void __iomem *base_addr; > + dma_addr_t dma_addr_rx; > + dma_addr_t dma_addr_tx; > struct clk *hclk; > struct clk *mclk; > struct reset_control *rstc; > @@ -92,6 +97,7 @@ struct sun6i_spi { > const u8 *tx_buf; > u8 *rx_buf; > int len; > + bool use_dma; > unsigned long fifo_depth; > }; > =20 > @@ -182,6 +188,66 @@ static size_t sun6i_spi_max_transfer_size(struct spi= _device *spi) > return SUN6I_MAX_XFER_SIZE - 1; > } > =20 > +static int sun6i_spi_prepare_dma(struct sun6i_spi *sspi, > + struct spi_transfer *tfr) > +{ > + struct dma_async_tx_descriptor *rxdesc, *txdesc; > + struct spi_master *master =3D sspi->master; > + > + rxdesc =3D NULL; > + if (tfr->rx_buf) { > + struct dma_slave_config rxconf =3D { > + .direction =3D DMA_DEV_TO_MEM, > + .src_addr =3D sspi->dma_addr_rx, > + .src_addr_width =3D 1, > + .src_maxburst =3D 1, > + }; That doesn't really look optimal, the controller seems to be able to read / write 32 bits at a time from its FIFO and we probably can increase the burst length too? > + > + dmaengine_slave_config(master->dma_rx, &rxconf); > + > + rxdesc =3D dmaengine_prep_slave_sg( > + master->dma_rx, > + tfr->rx_sg.sgl, tfr->rx_sg.nents, > + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); checkpatch --strict complains about this one (your line shouldn't end with a parenthesis). > + if (!rxdesc) > + return -EINVAL; > + } > + > + txdesc =3D NULL; > + if (tfr->tx_buf) { > + struct dma_slave_config txconf =3D { > + .direction =3D DMA_MEM_TO_DEV, > + .dst_addr =3D sspi->dma_addr_tx, > + .dst_addr_width =3D 1, > + .dst_maxburst =3D 1, > + }; > + > + dmaengine_slave_config(master->dma_tx, &txconf); > + > + txdesc =3D dmaengine_prep_slave_sg( > + master->dma_tx, > + tfr->tx_sg.sgl, tfr->tx_sg.nents, > + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); > + if (!txdesc) { > + if (rxdesc) > + dmaengine_terminate_sync(master->dma_rx); > + return -EINVAL; > + } > + } > + > + if (tfr->rx_buf) { > + dmaengine_submit(rxdesc); > + dma_async_issue_pending(master->dma_rx); > + } > + > + if (tfr->tx_buf) { > + dmaengine_submit(txdesc); > + dma_async_issue_pending(master->dma_tx); > + } > + > + return 0; > +} > + > static int sun6i_spi_transfer_one(struct spi_master *master, > struct spi_device *spi, > struct spi_transfer *tfr) > @@ -201,6 +267,8 @@ static int sun6i_spi_transfer_one(struct spi_master *= master, > sspi->tx_buf =3D tfr->tx_buf; > sspi->rx_buf =3D tfr->rx_buf; > sspi->len =3D tfr->len; > + sspi->use_dma =3D master->can_dma ? > + master->can_dma(master, spi, tfr) : false; > =20 > /* Clear pending interrupts */ > sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0); > @@ -216,9 +284,17 @@ static int sun6i_spi_transfer_one(struct spi_master = *master, > * (See spi-sun4i.c) > */ > trig_level =3D sspi->fifo_depth / 4 * 3; > - sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, > - (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) | > - (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS)); > + reg =3D (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) | > + (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS); > + > + if (sspi->use_dma) { > + if (tfr->tx_buf) > + reg |=3D SUN6I_FIFO_CTL_TF_DRQ_EN; > + if (tfr->rx_buf) > + reg |=3D SUN6I_FIFO_CTL_RF_DRQ_EN; > + } > + > + sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, reg); > =20 > /* > * Setup the transfer control register: Chip Select, > @@ -300,16 +376,28 @@ static int sun6i_spi_transfer_one(struct spi_master= *master, > sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len); > sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len); > =20 > - /* Fill the TX FIFO */ > - sun6i_spi_fill_fifo(sspi); > + if (!sspi->use_dma) { > + /* Fill the TX FIFO */ > + sun6i_spi_fill_fifo(sspi); > + } else { > + ret =3D sun6i_spi_prepare_dma(sspi, tfr); > + if (ret) { > + dev_warn(&master->dev, > + "%s: prepare DMA failed, ret=3D%d", > + dev_name(&spi->dev), ret); > + return ret; > + } > + } > =20 > /* Enable the interrupts */ > reg =3D SUN6I_INT_CTL_TC; > =20 > - if (rx_len > sspi->fifo_depth) > - reg |=3D SUN6I_INT_CTL_RF_RDY; > - if (tx_len > sspi->fifo_depth) > - reg |=3D SUN6I_INT_CTL_TF_ERQ; > + if (!sspi->use_dma) { > + if (rx_len > sspi->fifo_depth) > + reg |=3D SUN6I_INT_CTL_RF_RDY; > + if (tx_len > sspi->fifo_depth) > + reg |=3D SUN6I_INT_CTL_TF_ERQ; > + } > =20 > sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg); > =20 > @@ -332,6 +420,11 @@ static int sun6i_spi_transfer_one(struct spi_master = *master, > =20 > sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0); > =20 > + if (ret && sspi->use_dma) { > + dmaengine_terminate_sync(master->dma_rx); > + dmaengine_terminate_sync(master->dma_tx); > + } > + > return ret; > } > =20 > @@ -343,7 +436,8 @@ static irqreturn_t sun6i_spi_handler(int irq, void *d= ev_id) > /* Transfer complete */ > if (status & SUN6I_INT_CTL_TC) { > sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC); > - sun6i_spi_drain_fifo(sspi); > + if (!sspi->use_dma) > + sun6i_spi_drain_fifo(sspi); Is it causing any issue? The FIFO will be drained only if there's something remaining in the FIFO, which shouldn't happen with DMA? Maxime --qboiznam3rkxrap6 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCX41MiQAKCRDj7w1vZxhR xURAAQD2D/f4gllUD42fAjpjkz5DH/BOU3aL8doWmHSnE2PF8QEAscqzE9DFSfI/ Onc8zzd+eSxCXsLif90Bx7puB6Ifugg= =lObj -----END PGP SIGNATURE----- --qboiznam3rkxrap6-- --===============7206180444206808083== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel --===============7206180444206808083==--