From patchwork Sun Sep 11 17:45:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergiu Moga X-Patchwork-Id: 1676574 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=bViv81Oq; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=microchip.com header.i=@microchip.com header.a=rsa-sha256 header.s=mchp header.b=ydPfZKDK; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MQchh1Kqyz1yhR for ; Mon, 12 Sep 2022 03:50:44 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:CC :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=UH+R6YeQlKU34YdhPFvqBWzo0gWiMTa+sjWT5wrcyN0=; b=bViv81Oq0gmdSP E6DpokhEhKRTfZmY7vaNKRshE/sYm1gs9LiBUlaK5lBA4HF5yXZSS1Xeb6qR4A4lp/VkboITepAvp XLo2uZEyEXak1a2Pwrgj73sW758J2NnoFCLdvTeNDsr1v2ufPD41kGSP6RKFlcV93QSeM4fO0xuMl yOP+hVoruNGZgsrEQlqjOpAi7f8PGB8MEgh96AlkAhUmuYzSwdPVk4s0jHWHlt9P3Z1AKpdlS8dwN CAQPzg/NMXG2lHuncPFGHdHNzTGYFkdXox4QSbqCpBcst83F7RUpEFde1AgHP6YS727WaPVIGPt5d /AS6UDc91ruYzQiYEGPQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oXR5M-003Zxr-1O; Sun, 11 Sep 2022 17:49:36 +0000 Received: from esa.microchip.iphmx.com ([68.232.153.233]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oXR5D-003Zty-E9; Sun, 11 Sep 2022 17:49:32 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1662918567; x=1694454567; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=DRdg08gpOoz28YQW9HkCk1C4uZNwrUnmYkN2NocEwhY=; b=ydPfZKDKYE+NDqYg3gLWiv5Zlv62PAKheZYaXis2dxVc9ROQHVAPlIGJ VkGD+MQ2lRnb3uIj5rZByimGYTh4XWVxPr8e14Epl2Khzpoh6IMEocKjH t9nHB3nP2InMRKOdRWoHh8vH3M1h6/N7V8YngwVGVLIt3FiYJ1sLeiDXM 4E4V3AiqzVtrJY+2FoqI3KNLljNcbm/K8vovF4xrnJC22PArQ9/EkS2aq 08gh6qoN/pGMRaNAubu8mPp4W/oSJZ6mwUnspq70sTHf+JyBoW0NGvfrT svQOBl2CpbKdM34ckUw2ES13l3dGDspGIpHdyDHrTAo8fDz9j3O2et3hO g==; X-IronPort-AV: E=Sophos;i="5.93,307,1654585200"; d="scan'208";a="180043523" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 11 Sep 2022 10:49:21 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.12; Sun, 11 Sep 2022 10:49:20 -0700 Received: from ROB-ULT-M68701.amer.actel.com (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.12 via Frontend Transport; Sun, 11 Sep 2022 10:49:02 -0700 From: Sergiu Moga To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , CC: , , , , , , , , , , Sergiu Moga Subject: [PATCH] spi: Replace `dummy.nbytes` with `dummy.ncycles` Date: Sun, 11 Sep 2022 20:45:53 +0300 Message-ID: <20220911174551.653599-1-sergiu.moga@microchip.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220911_104927_646929_24F8FE54 X-CRM114-Status: GOOD ( 22.03 ) X-Spam-Score: -2.7 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: In order to properly represent the hardware functionality in the core, avoid reconverting the number of dummy cycles to the number of bytes and only work with the former. Instead, let the drivers that [...] Content analysis details: (-2.7 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [68.232.153.233 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.2 DKIMWL_WL_HIGH DKIMwl.org - High trust sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org In order to properly represent the hardware functionality in the core, avoid reconverting the number of dummy cycles to the number of bytes and only work with the former. Instead, let the drivers that do need this conversion do it themselves. Signed-off-by: Sergiu Moga Acked-by: Mark Brown --- drivers/mtd/spi-nor/core.c | 22 ++++---------- drivers/mtd/spi-nor/micron-st.c | 2 +- drivers/spi/atmel-quadspi.c | 6 ++-- drivers/spi/spi-aspeed-smc.c | 32 ++++++++++++++------- drivers/spi/spi-ath79.c | 2 +- drivers/spi/spi-bcm-qspi.c | 12 +++++--- drivers/spi/spi-cadence-quadspi.c | 8 ++---- drivers/spi/spi-cadence-xspi.c | 5 +++- drivers/spi/spi-dw-core.c | 10 +++++-- drivers/spi/spi-fsl-qspi.c | 17 ++++++----- drivers/spi/spi-hisi-sfc-v3xx.c | 6 +++- drivers/spi/spi-mem.c | 27 +++++++++++------ drivers/spi/spi-mt65xx.c | 33 ++++++++++++++------- drivers/spi/spi-mtk-nor.c | 48 +++++++++++++++++-------------- drivers/spi/spi-mtk-snfi.c | 24 ++++++++++------ drivers/spi/spi-mxic.c | 18 ++++++++---- drivers/spi/spi-npcm-fiu.c | 17 ++++++++--- drivers/spi/spi-nxp-fspi.c | 10 +++---- drivers/spi/spi-rockchip-sfc.c | 27 +++++++++++------ drivers/spi/spi-rpc-if.c | 5 ++-- drivers/spi/spi-stm32-qspi.c | 5 ++-- drivers/spi/spi-ti-qspi.c | 12 ++++++-- drivers/spi/spi-zynq-qspi.c | 15 ++++++---- drivers/spi/spi-zynqmp-gqspi.c | 8 ++++-- include/linux/spi/spi-mem.h | 10 +++---- 25 files changed, 234 insertions(+), 147 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index f2c64006f8d7..cc8ca824f912 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -88,7 +88,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor, if (op->addr.nbytes) op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto); - if (op->dummy.nbytes) + if (op->dummy.ncycles) op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto); if (op->data.nbytes) @@ -106,9 +106,6 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor, op->dummy.dtr = true; op->data.dtr = true; - /* 2 bytes per clock cycle in DTR mode. */ - op->dummy.nbytes *= 2; - ext = spi_nor_get_cmd_ext(nor, op); op->cmd.opcode = (op->cmd.opcode << 8) | ext; op->cmd.nbytes = 2; @@ -207,10 +204,7 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from, spi_nor_spimem_setup_op(nor, &op, nor->read_proto); - /* convert the dummy cycles to the number of bytes */ - op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; - if (spi_nor_protocol_is_dtr(nor->read_proto)) - op.dummy.nbytes *= 2; + op.dummy.ncycles = nor->read_dummy; usebouncebuf = spi_nor_spimem_bounce(nor, &op); @@ -455,7 +449,7 @@ int spi_nor_read_sr(struct spi_nor *nor, u8 *sr) if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) { op.addr.nbytes = nor->params->rdsr_addr_nbytes; - op.dummy.nbytes = nor->params->rdsr_dummy; + op.dummy.ncycles = nor->params->rdsr_dummy; /* * We don't want to read only one byte in DTR mode. So, * read 2 and then discard the second byte. @@ -1913,10 +1907,7 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor, spi_nor_spimem_setup_op(nor, &op, read->proto); - /* convert the dummy cycles to the number of bytes */ - op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; - if (spi_nor_protocol_is_dtr(nor->read_proto)) - op.dummy.nbytes *= 2; + op.dummy.ncycles = nor->read_dummy; return spi_nor_spimem_check_op(nor, &op); } @@ -3034,10 +3025,7 @@ static int spi_nor_create_read_dirmap(struct spi_nor *nor) spi_nor_spimem_setup_op(nor, op, nor->read_proto); - /* convert the dummy cycles to the number of bytes */ - op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8; - if (spi_nor_protocol_is_dtr(nor->read_proto)) - op->dummy.nbytes *= 2; + op->dummy.ncycles = nor->read_dummy; /* * Since spi_nor_spimem_setup_op() only sets buswidth when the number diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c index 3c9681a3f7a3..840a9fc0a888 100644 --- a/drivers/mtd/spi-nor/micron-st.c +++ b/drivers/mtd/spi-nor/micron-st.c @@ -337,7 +337,7 @@ static int micron_st_nor_read_fsr(struct spi_nor *nor, u8 *fsr) if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) { op.addr.nbytes = nor->params->rdsr_addr_nbytes; - op.dummy.nbytes = nor->params->rdsr_dummy; + op.dummy.ncycles = nor->params->rdsr_dummy; /* * We don't want to read only one byte in DTR mode. So, * read 2 and then discard the second byte. diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 976a217e356d..9a86525e7a4a 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -286,7 +286,7 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem, /* special case not supported by hardware */ if (op->addr.nbytes == 2 && op->cmd.buswidth != op->addr.buswidth && - op->dummy.nbytes == 0) + op->dummy.ncycles == 0) return false; return true; @@ -308,8 +308,8 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, return mode; ifr |= atmel_qspi_modes[mode].config; - if (op->dummy.nbytes) - dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth; + if (op->dummy.ncycles) + dummy_cycles = op->dummy.ncycles; /* * The controller allows 24 and 32-bit addressing while NAND-flash diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 3e891bf22470..2d50d50a9303 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -231,7 +231,7 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip, u64 offset, size_t len, void *buf) { int io_mode = aspeed_spi_get_io_mode(op); - u8 dummy = 0xFF; + u8 dummy = 0xFF, dummy_nbytes; int i; int ret; @@ -241,8 +241,12 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip, if (ret < 0) return ret; - if (op->dummy.buswidth && op->dummy.nbytes) { - for (i = 0; i < op->dummy.nbytes / op->dummy.buswidth; i++) + if (op->dummy.buswidth && op->dummy.ncycles) { + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + + for (i = 0; i < dummy_nbytes / op->dummy.buswidth; i++) aspeed_spi_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); } @@ -270,6 +274,8 @@ static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip, /* support for 1-1-1, 1-1-2 or 1-1-4 */ static bool aspeed_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { + u8 dummy_nbytes; + if (op->cmd.buswidth > 1) return false; @@ -280,8 +286,12 @@ static bool aspeed_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op return false; } - if (op->dummy.nbytes != 0) { - if (op->dummy.buswidth > 1 || op->dummy.nbytes > 7) + if (op->dummy.ncycles != 0) { + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + + if (op->dummy.buswidth > 1 || dummy_nbytes > 7) return false; } @@ -306,7 +316,7 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o chip->cs, op->data.dir == SPI_MEM_DATA_IN ? "read" : "write", op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, op->dummy.buswidth, op->data.buswidth, - op->addr.nbytes, op->dummy.nbytes, op->data.nbytes); + op->addr.nbytes, op->dummy.ncycles, op->data.nbytes); addr_mode = readl(aspi->regs + CE_CTRL_REG); addr_mode_backup = addr_mode; @@ -327,8 +337,8 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o ctl_val |= CTRL_IO_ADDRESS_4B; } - if (op->dummy.nbytes) - ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.nbytes / op->dummy.buswidth); + if (op->dummy.ncycles) + ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.ncycles / 8); if (op->data.nbytes) ctl_val |= aspeed_spi_get_io_mode(op); @@ -564,7 +574,7 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) desc->info.offset, desc->info.offset + desc->info.length, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, op->dummy.buswidth, op->data.buswidth, - op->addr.nbytes, op->dummy.nbytes); + op->addr.nbytes, op->dummy.ncycles); chip->clk_freq = desc->mem->spi->max_speed_hz; @@ -584,8 +594,8 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) op->cmd.opcode << CTRL_COMMAND_SHIFT | CTRL_IO_MODE_READ; - if (op->dummy.nbytes) - ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.nbytes / op->dummy.buswidth); + if (op->dummy.ncycles) + ctl_val |= CTRL_IO_DUMMY_SET(op->dummy.ncycles / 8); /* Tune 4BYTE address mode */ if (op->addr.nbytes) { diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 607e7a49fb89..70bdb1eb42a2 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -145,7 +145,7 @@ static int ath79_exec_mem_op(struct spi_mem *mem, /* Only use for fast-read op. */ if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN || - op->addr.nbytes != 3 || op->dummy.nbytes != 1) + op->addr.nbytes != 3 || op->dummy.ncycles != 8) return -ENOTSUPP; /* disable GPIO mode */ diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index cad2d55dcd3d..143e411c1523 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -428,8 +428,8 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, if (addrlen == BSPI_ADDRLEN_4BYTES) bpp = BSPI_BPP_ADDR_SELECT_MASK; - if (op->dummy.nbytes) - bpp |= (op->dummy.nbytes * 8) / op->dummy.buswidth; + if (op->dummy.ncycles) + bpp |= op->dummy.ncycles; switch (width) { case SPI_NBITS_SINGLE: @@ -1153,12 +1153,16 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi, struct spi_master *master = spi->master; struct bcm_qspi *qspi = spi_master_get_devdata(master); struct spi_transfer t[2]; - u8 cmd[6] = { }; + u8 cmd[6] = { }, dummy_nbytes; int ret, i; memset(cmd, 0, sizeof(cmd)); memset(t, 0, sizeof(t)); + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + /* tx */ /* opcode is in cmd[0] */ cmd[0] = op->cmd.opcode; @@ -1166,7 +1170,7 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi, cmd[1 + i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); t[0].tx_buf = cmd; - t[0].len = op->addr.nbytes + op->dummy.nbytes + 1; + t[0].len = op->addr.nbytes + dummy_nbytes + 1; t[0].bits_per_word = spi->bits_per_word; t[0].tx_nbits = op->cmd.buswidth; /* lets mspi know that this is not last transfer */ diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 72b1a5a2298c..2af43ba4a2cb 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -356,12 +356,10 @@ static unsigned int cqspi_calc_dummy(const struct spi_mem_op *op) { unsigned int dummy_clk; - if (!op->dummy.nbytes) + if (!op->dummy.ncycles) return 0; - dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth); - if (op->cmd.dtr) - dummy_clk /= 2; + dummy_clk = op->dummy.ncycles; return dummy_clk; } @@ -1333,7 +1331,7 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem, */ all_true = op->cmd.dtr && (!op->addr.nbytes || op->addr.dtr) && - (!op->dummy.nbytes || op->dummy.dtr) && + (!op->dummy.ncycles || op->dummy.dtr) && (!op->data.nbytes || op->data.dtr); all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr && diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index 3ab19be83095..8575e4c2ed7a 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c @@ -177,7 +177,10 @@ #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op) ( \ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_DCNT_H, \ ((op)->data.nbytes >> 16) & 0xffff) | \ - FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, (op)->dummy.nbytes * 8)) + FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, \ + ((op)->dummy.dtr ? \ + ((op)->dummy.ncycles * (op)->dummy.buswidth * 2) : \ + ((op)->dummy.ncycles * (op)->dummy.buswidth)))) #define CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op, chipsel) ( \ FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_BANK, chipsel) | \ diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c index f87d97ccd2d6..0ba5c7d0e66e 100644 --- a/drivers/spi/spi-dw-core.c +++ b/drivers/spi/spi-dw-core.c @@ -498,13 +498,17 @@ static bool dw_spi_supports_mem_op(struct spi_mem *mem, static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op) { unsigned int i, j, len; - u8 *out; + u8 *out, dummy_nbytes; /* * Calculate the total length of the EEPROM command transfer and * either use the pre-allocated buffer or create a temporary one. */ - len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + + len = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes; if (op->data.dir == SPI_MEM_DATA_OUT) len += op->data.nbytes; @@ -525,7 +529,7 @@ static int dw_spi_init_mem_buf(struct dw_spi *dws, const struct spi_mem_op *op) out[i] = DW_SPI_GET_BYTE(op->cmd.opcode, op->cmd.nbytes - i - 1); for (j = 0; j < op->addr.nbytes; ++i, ++j) out[i] = DW_SPI_GET_BYTE(op->addr.val, op->addr.nbytes - j - 1); - for (j = 0; j < op->dummy.nbytes; ++i, ++j) + for (j = 0; j < dummy_nbytes; ++i, ++j) out[i] = 0x0; if (op->data.dir == SPI_MEM_DATA_OUT) diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index 46ae46a944c5..897e8f11ccd1 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -369,6 +369,7 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + u8 dummy_nbytes; int ret; ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth); @@ -376,7 +377,7 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem, if (op->addr.nbytes) ret |= fsl_qspi_check_buswidth(q, op->addr.buswidth); - if (op->dummy.nbytes) + if (op->dummy.ncycles) ret |= fsl_qspi_check_buswidth(q, op->dummy.buswidth); if (op->data.nbytes) @@ -389,14 +390,17 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem, * The number of instructions needed for the op, needs * to fit into a single LUT entry. */ + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + if (op->addr.nbytes + - (op->dummy.nbytes ? 1:0) + + (dummy_nbytes ? 1:0) + (op->data.nbytes ? 1:0) > 6) return false; /* Max 64 dummy clock cycles supported */ - if (op->dummy.nbytes && - (op->dummy.nbytes * 8 / op->dummy.buswidth > 64)) + if (op->dummy.ncycles && op->dummy.ncycles > 64) return false; /* Max data length, check controller limits and alignment */ @@ -437,11 +441,10 @@ static void fsl_qspi_prepare_lut(struct fsl_qspi *q, lutidx++; } - if (op->dummy.nbytes) { + if (op->dummy.ncycles) { lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY, LUT_PAD(op->dummy.buswidth), - op->dummy.nbytes * 8 / - op->dummy.buswidth); + op->dummy.ncycles); lutidx++; } diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index d3a23b1c2a4c..5b6994eb7c8b 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -276,6 +276,7 @@ static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host *host, { int len = op->data.nbytes, buswidth_mode; u32 config = 0; + u8 dummy_nbytes; if (op->addr.nbytes) config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK; @@ -302,7 +303,10 @@ static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host *host, if (op->data.dir == SPI_MEM_DATA_IN) config |= HISI_SFC_V3XX_CMD_CFG_RW_MSK; - config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF | + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + config |= dummy_nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF | chip_select << HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF | HISI_SFC_V3XX_CMD_CFG_START_MSK; diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 0c79193d9697..7b204963bb62 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -149,7 +149,7 @@ static bool spi_mem_check_buswidth(struct spi_mem *mem, spi_check_buswidth_req(mem, op->addr.buswidth, true)) return false; - if (op->dummy.nbytes && + if (op->dummy.ncycles && spi_check_buswidth_req(mem, op->dummy.buswidth, true)) return false; @@ -202,7 +202,7 @@ static int spi_mem_check_op(const struct spi_mem_op *op) return -EINVAL; if ((op->addr.nbytes && !op->addr.buswidth) || - (op->dummy.nbytes && !op->dummy.buswidth) || + (op->dummy.ncycles && !op->dummy.buswidth) || (op->data.nbytes && !op->data.buswidth)) return -EINVAL; @@ -315,7 +315,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) struct spi_controller *ctlr = mem->spi->controller; struct spi_transfer xfers[4] = { }; struct spi_message msg; - u8 *tmpbuf; + u8 *tmpbuf, dummy_nbytes; int ret; ret = spi_mem_check_op(op); @@ -343,7 +343,11 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) return ret; } - tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + + tmpbufsize = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes; /* * Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so @@ -379,15 +383,15 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) totalxferlen += op->addr.nbytes; } - if (op->dummy.nbytes) { - memset(tmpbuf + op->addr.nbytes + 1, 0xff, op->dummy.nbytes); + if (dummy_nbytes) { + memset(tmpbuf + op->addr.nbytes + 1, 0xff, dummy_nbytes); xfers[xferpos].tx_buf = tmpbuf + op->addr.nbytes + 1; - xfers[xferpos].len = op->dummy.nbytes; + xfers[xferpos].len = dummy_nbytes; xfers[xferpos].tx_nbits = op->dummy.buswidth; xfers[xferpos].dummy_data = 1; spi_message_add_tail(&xfers[xferpos], &msg); xferpos++; - totalxferlen += op->dummy.nbytes; + totalxferlen += dummy_nbytes; } if (op->data.nbytes) { @@ -456,12 +460,17 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { struct spi_controller *ctlr = mem->spi->controller; size_t len; + u8 dummy_nbytes; if (ctlr->mem_ops && ctlr->mem_ops->adjust_op_size) return ctlr->mem_ops->adjust_op_size(mem, op); + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; + if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) { - len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; + len = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes; if (len > spi_max_transfer_size(mem->spi)) return -EINVAL; diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 0a3b9f7eed30..22d002acebe8 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -845,9 +845,13 @@ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { int opcode_len; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; if (op->data.dir != SPI_MEM_NO_DATA) { - opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes; + opcode_len = 1 + op->addr.nbytes + dummy_nbytes; if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len; /* force data buffer dma-aligned. */ @@ -861,14 +865,19 @@ static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, static bool mtk_spi_mem_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; + if (!spi_mem_default_supports_op(mem, op)) return false; - if (op->addr.nbytes && op->dummy.nbytes && + if (op->addr.nbytes && dummy_nbytes && op->addr.buswidth != op->dummy.buswidth) return false; - if (op->addr.nbytes + op->dummy.nbytes > 16) + if (op->addr.nbytes + dummy_nbytes > 16) return false; if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { @@ -942,6 +951,10 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, u32 reg_val, nio, tx_size; char *tx_tmp_buf, *rx_tmp_buf; int ret = 0; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; mdata->use_spimem = true; reinit_completion(&mdata->spimem_done); @@ -957,8 +970,8 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, /* addr & dummy byte len */ reg_val &= ~SPI_CFG3_IPM_ADDR_BYTELEN_MASK; - if (op->addr.nbytes || op->dummy.nbytes) - reg_val |= (op->addr.nbytes + op->dummy.nbytes) << + if (op->addr.nbytes || dummy_nbytes) + reg_val |= (op->addr.nbytes + dummy_nbytes) << SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET; /* data byte len */ @@ -971,7 +984,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, mtk_spi_setup_packet(mem->spi->master); } - if (op->addr.nbytes || op->dummy.nbytes) { + if (op->addr.nbytes || dummy_nbytes) { if (op->addr.buswidth == 1 || op->dummy.buswidth == 1) reg_val |= SPI_CFG3_IPM_XMODE_EN; else @@ -999,7 +1012,7 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR; writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); - tx_size = 1 + op->addr.nbytes + op->dummy.nbytes; + tx_size = 1 + op->addr.nbytes + dummy_nbytes; if (op->data.dir == SPI_MEM_DATA_OUT) tx_size += op->data.nbytes; @@ -1021,13 +1034,13 @@ static int mtk_spi_mem_exec_op(struct spi_mem *mem, (8 * (op->addr.nbytes - i - 1)); } - if (op->dummy.nbytes) + if (dummy_nbytes) memset(tx_tmp_buf + op->addr.nbytes + 1, 0xff, - op->dummy.nbytes); + dummy_nbytes); if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) - memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1, + memcpy(tx_tmp_buf + dummy_nbytes + op->addr.nbytes + 1, op->data.buf.out, op->data.nbytes); diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index d167699a1a96..f6870c6e911a 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -171,23 +171,18 @@ static bool need_bounce(struct mtk_nor *sp, const struct spi_mem_op *op) static bool mtk_nor_match_read(const struct spi_mem_op *op) { - int dummy = 0; - - if (op->dummy.nbytes) - dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth; - if ((op->data.buswidth == 2) || (op->data.buswidth == 4)) { if (op->addr.buswidth == 1) - return dummy == 8; + return op->dummy.ncycles == 8; else if (op->addr.buswidth == 2) - return dummy == 4; + return op->dummy.ncycles == 4; else if (op->addr.buswidth == 4) - return dummy == 6; + return op->dummy.ncycles == 6; } else if ((op->addr.buswidth == 1) && (op->data.buswidth == 1)) { if (op->cmd.opcode == 0x03) - return dummy == 0; + return op->dummy.ncycles == 0; else if (op->cmd.opcode == 0x0b) - return dummy == 8; + return op->dummy.ncycles == 8; } return false; } @@ -195,6 +190,10 @@ static bool mtk_nor_match_read(const struct spi_mem_op *op) static bool mtk_nor_match_prg(const struct spi_mem_op *op) { int tx_len, rx_len, prg_len, prg_left; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; // prg mode is spi-only. if ((op->cmd.buswidth > 1) || (op->addr.buswidth > 1) || @@ -205,7 +204,7 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op) if (op->data.dir == SPI_MEM_DATA_OUT) { // count dummy bytes only if we need to write data after it - tx_len += op->dummy.nbytes; + tx_len += dummy_nbytes; // leave at least one byte for data if (tx_len > MTK_NOR_REG_PRGDATA_MAX) @@ -221,7 +220,7 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op) return false; rx_len = op->data.nbytes; - prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - op->dummy.nbytes; + prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - dummy_nbytes; if (prg_left > MTK_NOR_REG_SHIFT_MAX + 1) prg_left = MTK_NOR_REG_SHIFT_MAX + 1; if (rx_len > prg_left) { @@ -230,11 +229,11 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op) rx_len = prg_left; } - prg_len = tx_len + op->dummy.nbytes + rx_len; + prg_len = tx_len + dummy_nbytes + rx_len; if (prg_len > MTK_NOR_PRG_CNT_MAX / 8) return false; } else { - prg_len = tx_len + op->dummy.nbytes; + prg_len = tx_len + dummy_nbytes; if (prg_len > MTK_NOR_PRG_CNT_MAX / 8) return false; } @@ -244,15 +243,19 @@ static bool mtk_nor_match_prg(const struct spi_mem_op *op) static void mtk_nor_adj_prg_size(struct spi_mem_op *op) { int tx_len, tx_left, prg_left; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; tx_len = op->cmd.nbytes + op->addr.nbytes; if (op->data.dir == SPI_MEM_DATA_OUT) { - tx_len += op->dummy.nbytes; + tx_len += dummy_nbytes; tx_left = MTK_NOR_REG_PRGDATA_MAX + 1 - tx_len; if (op->data.nbytes > tx_left) op->data.nbytes = tx_left; } else if (op->data.dir == SPI_MEM_DATA_IN) { - prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - op->dummy.nbytes; + prg_left = MTK_NOR_PRG_CNT_MAX / 8 - tx_len - dummy_nbytes; if (prg_left > MTK_NOR_REG_SHIFT_MAX + 1) prg_left = MTK_NOR_REG_SHIFT_MAX + 1; if (op->data.nbytes > prg_left) @@ -312,7 +315,7 @@ static bool mtk_nor_supports_op(struct spi_mem *mem, break; case SPI_MEM_DATA_OUT: if ((op->addr.buswidth == 1) && - (op->dummy.nbytes == 0) && + (op->dummy.ncycles == 0) && (op->data.buswidth == 1)) return true; break; @@ -515,17 +518,20 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op) int tx_len, prg_len; int i, ret; void __iomem *reg; - u8 bufbyte; + u8 bufbyte, dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; tx_len = op->cmd.nbytes + op->addr.nbytes; // count dummy bytes only if we need to write data after it if (op->data.dir == SPI_MEM_DATA_OUT) - tx_len += op->dummy.nbytes + op->data.nbytes; + tx_len += dummy_nbytes + op->data.nbytes; else if (op->data.dir == SPI_MEM_DATA_IN) rx_len = op->data.nbytes; - prg_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes + + prg_len = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes + op->data.nbytes; // an invalid op may reach here if the caller calls exec_op without @@ -550,7 +556,7 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op) } if (op->data.dir == SPI_MEM_DATA_OUT) { - for (i = 0; i < op->dummy.nbytes; i++, reg_offset--) { + for (i = 0; i < dummy_nbytes; i++, reg_offset--) { reg = sp->base + MTK_NOR_REG_PRGDATA(reg_offset); writeb(0, reg); } diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c index d66bf9762557..05d2f0a97feb 100644 --- a/drivers/spi/spi-mtk-snfi.c +++ b/drivers/spi/spi-mtk-snfi.c @@ -434,7 +434,10 @@ static int mtk_snand_mac_io(struct mtk_snand *snf, const struct spi_mem_op *op) const u8 *tx_buf = NULL; u8 *rx_buf = NULL; int i, ret; - u8 b; + u8 b, dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; if (op->data.dir == SPI_MEM_DATA_IN) { rx_len = op->data.nbytes; @@ -463,7 +466,7 @@ static int mtk_snand_mac_io(struct mtk_snand *snf, const struct spi_mem_op *op) } } - for (i = 0; i < op->dummy.nbytes; i++, reg_offs++) { + for (i = 0; i < dummy_nbytes; i++, reg_offs++) { if (reg_offs % 4 == 3) { nfi_write32(snf, SNF_GPRAM + reg_offs - 3, val); val = 0; @@ -836,7 +839,7 @@ static int mtk_snand_read_page_cache(struct mtk_snand *snf, u32 op_addr = op->addr.val; // where to start copying data from bounce buffer u32 rd_offset = 0; - u32 dummy_clk = (op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth); + u32 dummy_clk = op->dummy.ncycles; u32 op_mode = 0; u32 dma_len = snf->buf_len; int ret = 0; @@ -1178,8 +1181,7 @@ static bool mtk_snand_is_page_ops(const struct spi_mem_op *op) // match read from page instructions if (op->data.dir == SPI_MEM_DATA_IN) { // check dummy cycle first - if (op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth > - DATA_READ_MAX_DUMMY) + if (op->dummy.ncycles > DATA_READ_MAX_DUMMY) return false; // quad io / quad out if ((op->addr.buswidth == 4 || op->addr.buswidth == 1) && @@ -1196,7 +1198,7 @@ static bool mtk_snand_is_page_ops(const struct spi_mem_op *op) return true; } else if (op->data.dir == SPI_MEM_DATA_OUT) { // check dummy cycle first - if (op->dummy.nbytes) + if (op->dummy.ncycles) return false; // program load quad out if (op->addr.buswidth == 1 && op->data.buswidth == 4) @@ -1218,7 +1220,7 @@ static bool mtk_snand_supports_op(struct spi_mem *mem, if (mtk_snand_is_page_ops(op)) return true; return ((op->addr.nbytes == 0 || op->addr.buswidth == 1) && - (op->dummy.nbytes == 0 || op->dummy.buswidth == 1) && + (op->dummy.ncycles == 0 || op->dummy.buswidth == 1) && (op->data.nbytes == 0 || op->data.buswidth == 1)); } @@ -1239,7 +1241,13 @@ static int mtk_snand_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) if (op->data.nbytes > l) op->data.nbytes = l; } else { - size_t hl = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; + size_t hl; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; + + hl = op->cmd.nbytes + op->addr.nbytes + dummy_nbytes; if (hl >= SNF_GPRAM_SIZE) return -EOPNOTSUPP; diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index 65be8e085ab8..d940ee0e11a5 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -316,14 +316,18 @@ static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op, u32 cfg = OP_CMD_BYTES(op->cmd.nbytes) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) | (op->cmd.dtr ? OP_CMD_DDR : 0); + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; if (op->addr.nbytes) cfg |= OP_ADDR_BYTES(op->addr.nbytes) | OP_ADDR_BUSW(fls(op->addr.buswidth) - 1) | (op->addr.dtr ? OP_ADDR_DDR : 0); - if (op->dummy.nbytes) - cfg |= OP_DUMMY_CYC(op->dummy.nbytes); + if (dummy_nbytes) + cfg |= OP_DUMMY_CYC(dummy_nbytes); /* Direct mapping data.nbytes field is not populated */ if (data_len) { @@ -481,7 +485,7 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem, op->dummy.buswidth > 8 || op->cmd.buswidth > 8) return false; - if (op->data.nbytes && op->dummy.nbytes && + if (op->data.nbytes && op->dummy.ncycles && op->data.buswidth != op->dummy.buswidth) return false; @@ -512,7 +516,11 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, { struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master); int i, ret; - u8 addr[8], cmd[2]; + u8 addr[8], cmd[2], dummy_nbytes; + + dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + if (op->dummy.dtr) + dummy_nbytes *= 2; ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz); if (ret) @@ -543,7 +551,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, if (ret) goto out; - ret = mxic_spi_data_xfer(mxic, NULL, NULL, op->dummy.nbytes); + ret = mxic_spi_data_xfer(mxic, NULL, NULL, dummy_nbytes); if (ret) goto out; diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index 49f6424e35af..17493f668459 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -265,6 +265,11 @@ static const struct regmap_config npcm_mtd_regmap_config = { static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu, const struct spi_mem_op *op) { + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, NPCM_FIU_DRD_CFG_ACCTYPE, ilog2(op->addr.buswidth) << @@ -272,8 +277,8 @@ static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu, fiu->drd_op.addr.buswidth = op->addr.buswidth; regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, NPCM_FIU_DRD_CFG_DBW, - op->dummy.nbytes << NPCM_FIU_DRD_DBW_SHIFT); - fiu->drd_op.dummy.nbytes = op->dummy.nbytes; + dummy_nbytes << NPCM_FIU_DRD_DBW_SHIFT); + fiu->drd_op.dummy.ncycles = op->dummy.ncycles; regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode); fiu->drd_op.cmd.opcode = op->cmd.opcode; @@ -299,7 +304,7 @@ static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc, *(buf_rx + i) = ioread8(src + i); } else { if (desc->info.op_tmpl.addr.buswidth != fiu->drd_op.addr.buswidth || - desc->info.op_tmpl.dummy.nbytes != fiu->drd_op.dummy.nbytes || + desc->info.op_tmpl.dummy.ncycles != fiu->drd_op.dummy.ncycles || desc->info.op_tmpl.cmd.opcode != fiu->drd_op.cmd.opcode || desc->info.op_tmpl.addr.nbytes != fiu->drd_op.addr.nbytes) npcm_fiu_set_drd(fiu, &desc->info.op_tmpl); @@ -341,6 +346,10 @@ static int npcm_fiu_uma_read(struct spi_mem *mem, int ret; u32 val; u32 i; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, NPCM_FIU_UMA_CTS_DEV_NUM, @@ -357,7 +366,7 @@ static int npcm_fiu_uma_read(struct spi_mem *mem, << NPCM_FIU_UMA_CFG_DBPCK_SHIFT; uma_cfg |= ilog2(op->data.buswidth) << NPCM_FIU_UMA_CFG_RDBPCK_SHIFT; - uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT; + uma_cfg |= dummy_nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT; uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT; regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, addr); } else { diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 2b0301fc971c..ccec9b726283 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -444,7 +444,7 @@ static bool nxp_fspi_supports_op(struct spi_mem *mem, if (op->addr.nbytes) ret |= nxp_fspi_check_buswidth(f, op->addr.buswidth); - if (op->dummy.nbytes) + if (op->dummy.ncycles) ret |= nxp_fspi_check_buswidth(f, op->dummy.buswidth); if (op->data.nbytes) @@ -468,8 +468,7 @@ static bool nxp_fspi_supports_op(struct spi_mem *mem, return false; /* Max 64 dummy clock cycles supported */ - if (op->dummy.buswidth && - (op->dummy.nbytes * 8 / op->dummy.buswidth > 64)) + if (op->dummy.ncycles > 64) return false; /* Max data length, check controller limits and alignment */ @@ -543,15 +542,14 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, } /* dummy bytes, if needed */ - if (op->dummy.nbytes) { + if (op->dummy.ncycles) { lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY, /* * Due to FlexSPI controller limitation number of PAD for dummy * buswidth needs to be programmed as equal to data buswidth. */ LUT_PAD(op->data.buswidth), - op->dummy.nbytes * 8 / - op->dummy.buswidth); + op->dummy.ncycles); lutidx++; } diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c index bd87d3c92dd3..82f9e61b9036 100644 --- a/drivers/spi/spi-rockchip-sfc.c +++ b/drivers/spi/spi-rockchip-sfc.c @@ -282,16 +282,21 @@ static int rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc *sfc, u32 timeout_ static void rockchip_sfc_adjust_op_work(struct spi_mem_op *op) { - if (unlikely(op->dummy.nbytes && !op->addr.nbytes)) { + if (unlikely(op->dummy.ncycles && !op->addr.nbytes)) { + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; + /* * SFC not support output DUMMY cycles right after CMD cycles, so * treat it as ADDR cycles. */ - op->addr.nbytes = op->dummy.nbytes; + op->addr.nbytes = dummy_nbytes; op->addr.buswidth = op->dummy.buswidth; op->addr.val = 0xFFFFFFFFF; - op->dummy.nbytes = 0; + op->dummy.ncycles = 0; } } @@ -301,6 +306,10 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, u32 len) { u32 ctrl = 0, cmd = 0; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; /* set CMD */ cmd = op->cmd.opcode; @@ -321,13 +330,13 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, } /* set DUMMY */ - if (op->dummy.nbytes) { + if (dummy_nbytes) { if (op->dummy.buswidth == 4) - cmd |= op->dummy.nbytes * 2 << SFC_CMD_DUMMY_SHIFT; + cmd |= dummy_nbytes * 2 << SFC_CMD_DUMMY_SHIFT; else if (op->dummy.buswidth == 2) - cmd |= op->dummy.nbytes * 4 << SFC_CMD_DUMMY_SHIFT; + cmd |= dummy_nbytes * 4 << SFC_CMD_DUMMY_SHIFT; else - cmd |= op->dummy.nbytes * 8 << SFC_CMD_DUMMY_SHIFT; + cmd |= dummy_nbytes * 8 << SFC_CMD_DUMMY_SHIFT; } /* set DATA */ @@ -348,9 +357,9 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE; cmd |= mem->spi->chip_select << SFC_CMD_CS_SHIFT; - dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n", + dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.ncycles=%x(x%d)\n", op->addr.nbytes, op->addr.buswidth, - op->dummy.nbytes, op->dummy.buswidth); + op->dummy.ncycles, op->dummy.buswidth); dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n", ctrl, cmd, op->addr.val, len); diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c index 24ec1c83f379..fb317a80bef8 100644 --- a/drivers/spi/spi-rpc-if.c +++ b/drivers/spi/spi-rpc-if.c @@ -32,10 +32,9 @@ static void rpcif_spi_mem_prepare(struct spi_device *spi_dev, rpc_op.addr.val = spi_op->addr.val; } - if (spi_op->dummy.nbytes) { + if (spi_op->dummy.ncycles) { rpc_op.dummy.buswidth = spi_op->dummy.buswidth; - rpc_op.dummy.ncycles = spi_op->dummy.nbytes * 8 / - spi_op->dummy.buswidth; + rpc_op.dummy.ncycles = spi_op->dummy.ncycles; } if (spi_op->data.nbytes || (offs && len)) { diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index f3fe92300639..9072345eddde 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -388,9 +388,8 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1); } - if (op->dummy.nbytes) - ccr |= FIELD_PREP(CCR_DCYC_MASK, - op->dummy.nbytes * 8 / op->dummy.buswidth); + if (op->dummy.ncycles) + ccr |= FIELD_PREP(CCR_DCYC_MASK, op->dummy.ncycles); if (op->data.nbytes) { ccr |= FIELD_PREP(CCR_DMODE_MASK, diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 60086869bcae..377bc119344f 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -579,6 +579,10 @@ static int ti_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { struct ti_qspi *qspi = spi_controller_get_devdata(mem->spi->master); size_t max_len; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; if (op->data.dir == SPI_MEM_DATA_IN) { if (op->addr.val < qspi->mmap_size) { @@ -595,7 +599,7 @@ static int ti_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) * Adjust size to comply with the QSPI max frame length. */ max_len = QSPI_FRAME; - max_len -= 1 + op->addr.nbytes + op->dummy.nbytes; + max_len -= 1 + op->addr.nbytes + dummy_nbytes; op->data.nbytes = min((size_t) op->data.nbytes, max_len); } @@ -610,6 +614,10 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem, struct ti_qspi *qspi = spi_master_get_devdata(mem->spi->master); u32 from = 0; int ret = 0; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; /* Only optimize read path. */ if (!op->data.nbytes || op->data.dir != SPI_MEM_DATA_IN || @@ -628,7 +636,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem, ti_qspi_enable_memory_map(mem->spi); } ti_qspi_setup_mmap_read(mem->spi, op->cmd.opcode, op->data.buswidth, - op->addr.nbytes, op->dummy.nbytes); + op->addr.nbytes, dummy_nbytes); if (qspi->rx_chan) { struct sg_table sgt; diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index 78f31b61a2aa..84b7db85548c 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -527,7 +527,10 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem, { struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master); int err = 0, i; - u8 *tmpbuf; + u8 *tmpbuf, dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n", op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, @@ -568,17 +571,17 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem, err = -ETIMEDOUT; } - if (op->dummy.nbytes) { - tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL); + if (dummy_nbytes) { + tmpbuf = kzalloc(dummy_nbytes, GFP_KERNEL); if (!tmpbuf) return -ENOMEM; - memset(tmpbuf, 0xff, op->dummy.nbytes); + memset(tmpbuf, 0xff, dummy_nbytes); reinit_completion(&xqspi->data_completion); xqspi->txbuf = tmpbuf; xqspi->rxbuf = NULL; - xqspi->tx_bytes = op->dummy.nbytes; - xqspi->rx_bytes = op->dummy.nbytes; + xqspi->tx_bytes = dummy_nbytes; + xqspi->rx_bytes = dummy_nbytes; zynq_qspi_write_op(xqspi, ZYNQ_QSPI_FIFO_DEPTH, true); zynq_qspi_write(xqspi, ZYNQ_QSPI_IEN_OFFSET, ZYNQ_QSPI_IXR_RXTX_MASK); diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index c760aac070e5..b41abadef9a6 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -948,6 +948,10 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, u32 genfifoentry = 0; u16 opcode = op->cmd.opcode; u64 opaddr; + u8 dummy_nbytes = (op->dummy.ncycles * op->dummy.buswidth) / 8; + + if (op->dummy.dtr) + dummy_nbytes *= 2; dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n", op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, @@ -1006,14 +1010,14 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, } } - if (op->dummy.nbytes) { + if (dummy_nbytes) { xqspi->txbuf = NULL; xqspi->rxbuf = NULL; /* * xqspi->bytes_to_transfer here represents the dummy circles * which need to be sent. */ - xqspi->bytes_to_transfer = op->dummy.nbytes * 8 / op->dummy.buswidth; + xqspi->bytes_to_transfer = dummy_nbytes; xqspi->bytes_to_receive = 0; /* * Using op->data.buswidth instead of op->dummy.buswidth here because diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 2ba044d0d5e5..5fd45800af03 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -29,9 +29,9 @@ #define SPI_MEM_OP_NO_ADDR { } -#define SPI_MEM_OP_DUMMY(__nbytes, __buswidth) \ +#define SPI_MEM_OP_DUMMY(__ncycles, __buswidth) \ { \ - .nbytes = __nbytes, \ + .ncycles = __ncycles, \ .buswidth = __buswidth, \ } @@ -83,8 +83,8 @@ enum spi_mem_data_dir { * Note that only @addr.nbytes are taken into account in this * address value, so users should make sure the value fits in the * assigned number of bytes. - * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can - * be zero if the operation does not require dummy bytes + * @dummy.ncycles: number of dummy cycles after an opcode or address. Can + * be zero if the operation does not require dummy cycles * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not * @data.buswidth: number of IO lanes used to send/receive the data @@ -112,7 +112,7 @@ struct spi_mem_op { } addr; struct { - u8 nbytes; + u8 ncycles; u8 buswidth; u8 dtr : 1; } dummy;