From: Jagan Teki <jagan@amarulasolutions.com>
To: u-boot@lists.denx.de
Subject: [PATCH v3 1/3] spi: sifive: Fix QPP transfer
Date: Mon, 20 Apr 2020 18:22:36 +0530 [thread overview]
Message-ID: <20200420125238.9610-2-jagan@amarulasolutions.com> (raw)
In-Reply-To: <20200420125238.9610-1-jagan@amarulasolutions.com>
For historical reasons the existing logic of filling tx fifo
with data, rx fifo with NULL for tx transfer and filling rx
fifo with data, tx fifo with NULL for rx transfer is not
clear enough to support the Quad Page Program.
? ?
SiFive SPI controllers have specific sets of watermark
registers and SPI I/O directions bits in order to program
SPI controllers clear enough to support all sets of operating
modes.
? ?
Here is the exact programing sequence that would follow on this
patch and tested via SPI-NOR and MMC_SPI.
? ?
- set the frame format proto, endian
- set the frame format dir, set it for tx and clear it for rx
- TX transfer:
? fill tx fifo with data.
? wait for TX watermark bit to clear.
- TX transfer:
? fill tx fifo with 0xff.
? write nbytes to rx watermark register
? wait for rx watermark bit to clear.
? read the rx fifo data.
So, this patch adopts this program sequence and fixes the existing
I/O direction bit.
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v3:
- new patch
drivers/spi/spi-sifive.c | 57 ++++++++++++++++++++++++++--------------
1 file changed, 37 insertions(+), 20 deletions(-)
diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c
index 336b683476..2a0b28dc08 100644
--- a/drivers/spi/spi-sifive.c
+++ b/drivers/spi/spi-sifive.c
@@ -10,6 +10,7 @@
#include <dm.h>
#include <malloc.h>
#include <spi.h>
+#include <wait_bit.h>
#include <asm/io.h>
#include <linux/log2.h>
#include <clk.h>
@@ -127,8 +128,8 @@ static void sifive_spi_clear_cs(struct sifive_spi *spi)
}
static void sifive_spi_prep_transfer(struct sifive_spi *spi,
- bool is_rx_xfer,
- struct dm_spi_slave_platdata *slave_plat)
+ struct dm_spi_slave_platdata *slave_plat,
+ u8 *rx_ptr)
{
u32 cr;
@@ -160,7 +161,7 @@ static void sifive_spi_prep_transfer(struct sifive_spi *spi,
/* SPI direction in/out ? */
cr &= ~SIFIVE_SPI_FMT_DIR;
- if (!is_rx_xfer)
+ if (!rx_ptr)
cr |= SIFIVE_SPI_FMT_DIR;
writel(cr, spi->regs + SIFIVE_SPI_REG_FMT);
@@ -191,13 +192,19 @@ static void sifive_spi_tx(struct sifive_spi *spi, const u8 *tx_ptr)
writel(tx_data, spi->regs + SIFIVE_SPI_REG_TXDATA);
}
+static int sifive_spi_wait(struct sifive_spi *spi, u32 bit)
+{
+ return wait_for_bit_le32(spi->regs + SIFIVE_SPI_REG_IP,
+ bit, true, 100, false);
+}
+
static int sifive_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
struct udevice *bus = dev->parent;
struct sifive_spi *spi = dev_get_priv(bus);
struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
- const unsigned char *tx_ptr = dout;
+ const u8 *tx_ptr = dout;
u8 *rx_ptr = din;
u32 remaining_len;
int ret;
@@ -210,31 +217,37 @@ static int sifive_spi_xfer(struct udevice *dev, unsigned int bitlen,
return ret;
}
- sifive_spi_prep_transfer(spi, true, slave_plat);
+ sifive_spi_prep_transfer(spi, slave_plat, rx_ptr);
remaining_len = bitlen / 8;
while (remaining_len) {
- int n_words, tx_words, rx_words;
-
- n_words = min(remaining_len, spi->fifo_depth);
+ unsigned int n_words = min(remaining_len, spi->fifo_depth);
+ unsigned int tx_words, rx_words;
/* Enqueue n_words for transmission */
- if (tx_ptr) {
- for (tx_words = 0; tx_words < n_words; ++tx_words) {
- sifive_spi_tx(spi, tx_ptr);
- sifive_spi_rx(spi, NULL);
- tx_ptr++;
- }
+ for (tx_words = 0; tx_words < n_words; tx_words++) {
+ if (!tx_ptr)
+ sifive_spi_tx(spi, NULL);
+ else
+ sifive_spi_tx(spi, tx_ptr++);
}
- /* Read out all the data from the RX FIFO */
if (rx_ptr) {
- for (rx_words = 0; rx_words < n_words; ++rx_words) {
- sifive_spi_tx(spi, NULL);
- sifive_spi_rx(spi, rx_ptr);
- rx_ptr++;
- }
+ /* Wait for transmission + reception to complete */
+ writel(n_words - 1, spi->regs + SIFIVE_SPI_REG_RXMARK);
+ ret = sifive_spi_wait(spi, SIFIVE_SPI_IP_RXWM);
+ if (ret)
+ return ret;
+
+ /* Read out all the data from the RX FIFO */
+ for (rx_words = 0; rx_words < n_words; rx_words++)
+ sifive_spi_rx(spi, rx_ptr++);
+ } else {
+ /* Wait for transmission to complete */
+ ret = sifive_spi_wait(spi, SIFIVE_SPI_IP_TXWM);
+ if (ret)
+ return ret;
}
remaining_len -= n_words;
@@ -314,6 +327,10 @@ static void sifive_spi_init_hw(struct sifive_spi *spi)
/* Watermark interrupts are disabled by default */
writel(0, spi->regs + SIFIVE_SPI_REG_IE);
+ /* Default watermark FIFO threshold values */
+ writel(1, spi->regs + SIFIVE_SPI_REG_TXMARK);
+ writel(0, spi->regs + SIFIVE_SPI_REG_RXMARK);
+
/* Set CS/SCK Delays and Inactive Time to defaults */
writel(SIFIVE_SPI_DELAY0_CSSCK(1) | SIFIVE_SPI_DELAY0_SCKCS(1),
spi->regs + SIFIVE_SPI_REG_DELAY0);
--
2.17.1
next prev parent reply other threads:[~2020-04-20 12:52 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-20 12:52 [PATCH v3 0/3] riscv: sifive/fu540: Enable SPI-NOR support Jagan Teki
2020-04-20 12:52 ` Jagan Teki [this message]
2020-04-20 14:01 ` [PATCH v3 1/3] spi: sifive: Fix QPP transfer Bin Meng
2020-04-20 14:09 ` Jagan Teki
2020-04-20 14:15 ` Bin Meng
2020-04-20 14:16 ` Jagan Teki
2020-04-20 12:52 ` [PATCH v3 2/3] riscv: dts: hifive-unleashed-a00: Add -u-boot.dtsi Jagan Teki
2020-04-20 14:02 ` Bin Meng
2020-04-20 12:52 ` [PATCH v3 3/3] sifive: fu540: Enable spi-nor flash support Jagan Teki
2020-04-20 14:03 ` Bin Meng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200420125238.9610-2-jagan@amarulasolutions.com \
--to=jagan@amarulasolutions.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox