From: lee.jones@linaro.org (Lee Jones)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 29/37] mtd: st_spi_fsm: Add the ability to write to a Serial Flash device
Date: Wed, 8 Jan 2014 13:47:12 +0000 [thread overview]
Message-ID: <1389188840-14306-30-git-send-email-lee.jones@linaro.org> (raw)
In-Reply-To: <1389188840-14306-1-git-send-email-lee.jones@linaro.org>
When a write is requested by userspace the MFD framework calls back
into the driver to conduct the actual command issue and data send.
Here we provide the routines which do exactly that.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mtd/devices/st_spi_fsm.c | 150 +++++++++++++++++++++++++++++++++++++++
1 file changed, 150 insertions(+)
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c
index c2ee7e3..0b80d74 100644
--- a/drivers/mtd/devices/st_spi_fsm.c
+++ b/drivers/mtd/devices/st_spi_fsm.c
@@ -1078,6 +1078,98 @@ static int stfsm_read(struct stfsm *fsm, uint8_t *buf, uint32_t size,
return 0;
}
+static int stfsm_write(struct stfsm *fsm, const uint8_t *const buf,
+ const uint32_t size, const uint32_t offset)
+{
+ struct stfsm_seq *seq = &stfsm_seq_write;
+ uint32_t data_pads;
+ uint32_t write_mask;
+ uint32_t size_ub;
+ uint32_t size_lb;
+ uint32_t size_mop;
+ uint32_t tmp[4];
+ uint32_t page_buf[FLASH_PAGESIZE_32];
+ uint8_t *t = (uint8_t *)&tmp;
+ const uint8_t *p;
+ int ret;
+ int i;
+
+ dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset);
+
+ /* Enter 32-bit address mode, if required */
+ if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR)
+ stfsm_enter_32bit_addr(fsm, 1);
+
+ /* Must write in multiples of 32 cycles (or 32*pads/8 bytes) */
+ data_pads = ((seq->seq_cfg >> 16) & 0x3) + 1;
+ write_mask = (data_pads << 2) - 1;
+
+ /* Handle non-aligned buf */
+ if ((uint32_t)buf & 0x3) {
+ memcpy(page_buf, buf, size);
+ p = (uint8_t *)page_buf;
+ } else {
+ p = buf;
+ }
+
+ /* Handle non-aligned size */
+ size_ub = (size + write_mask) & ~write_mask;
+ size_lb = size & ~write_mask;
+ size_mop = size & write_mask;
+
+ seq->data_size = TRANSFER_SIZE(size_ub);
+ seq->addr1 = (offset >> 16) & 0xffff;
+ seq->addr2 = offset & 0xffff;
+
+ /* Need to set FIFO to write mode, before writing data to FIFO (see
+ * GNBvb79594)
+ */
+ writel(0x00040000, fsm->base + SPI_FAST_SEQ_CFG);
+
+ /*
+ * Before writing data to the FIFO, apply a small delay to allow a
+ * potential change of FIFO direction to complete.
+ */
+ if (fsm->fifo_dir_delay == 0)
+ readl(fsm->base + SPI_FAST_SEQ_CFG);
+ else
+ udelay(fsm->fifo_dir_delay);
+
+
+ /* Write data to FIFO, before starting sequence (see GNBvd79593) */
+ if (size_lb) {
+ stfsm_write_fifo(fsm, (uint32_t *)p, size_lb);
+ p += size_lb;
+ }
+
+ /* Handle non-aligned size */
+ if (size_mop) {
+ memset(t, 0xff, write_mask + 1); /* fill with 0xff's */
+ for (i = 0; i < size_mop; i++)
+ t[i] = *p++;
+
+ stfsm_write_fifo(fsm, tmp, write_mask + 1);
+ }
+
+ /* Start sequence */
+ stfsm_load_seq(fsm, seq);
+
+ /* Wait for sequence to finish */
+ stfsm_wait_seq(fsm);
+
+ /* Wait for completion */
+ ret = stfsm_wait_busy(fsm);
+
+ /* Exit 32-bit address mode, if required */
+ if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) {
+ stfsm_enter_32bit_addr(fsm, 0);
+ if (fsm->configuration & CFG_WRITE_EX_32BIT_ADDR_DELAY)
+ udelay(1);
+ }
+
+ return 0;
+}
+
/*
* Read an address range from the flash chip. The address range
* may be any size provided it is within the physical boundaries.
@@ -1111,6 +1203,63 @@ static int stfsm_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
return 0;
}
+/*
+ * Write an address range to the flash chip. Data must be written in
+ * FLASH_PAGESIZE chunks. The address range may be any size provided
+ * it is within the physical boundaries.
+ */
+static int stfsm_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent);
+
+ u32 page_offs;
+ u32 bytes;
+ uint8_t *b = (uint8_t *)buf;
+ int ret = 0;
+
+ dev_dbg(fsm->dev, "%s to 0x%08x, len %zd\n", __func__, (u32)to, len);
+
+ if (retlen)
+ *retlen = 0;
+
+ if (!len)
+ return 0;
+
+ if (to + len > mtd->size)
+ return -EINVAL;
+
+ /* Offset within page */
+ page_offs = to % FLASH_PAGESIZE;
+
+ mutex_lock(&fsm->lock);
+
+ while (len) {
+ /* Write up to page boundary */
+ bytes = min(FLASH_PAGESIZE - page_offs, len);
+
+ ret = stfsm_write(fsm, b, bytes, to);
+ if (ret)
+ goto out1;
+
+ b += bytes;
+ len -= bytes;
+ to += bytes;
+
+ /* We are now page-aligned */
+ page_offs = 0;
+
+ if (retlen)
+ *retlen += bytes;
+
+ }
+
+out1:
+ mutex_unlock(&fsm->lock);
+
+ return ret;
+}
+
static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec)
{
const struct stfsm_seq *seq = &stfsm_seq_read_jedec;
@@ -1380,6 +1529,7 @@ static int stfsm_probe(struct platform_device *pdev)
fsm->mtd.erasesize = info->sector_size;
fsm->mtd._read = stfsm_mtd_read;
+ fsm->mtd._write = stfsm_mtd_write;
dev_err(&pdev->dev,
"Found serial flash device: %s\n"
--
1.8.3.2
next prev parent reply other threads:[~2014-01-08 13:47 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-08 13:46 [PATCH v4 00/36] mtd: st_spi_fsm: Add new driver Lee Jones
2014-01-08 13:46 ` [PATCH v4 01/37] mtd: st_spi_fsm: Allocate resources and register with MTD framework Lee Jones
2014-01-08 13:46 ` [PATCH v4 02/37] mtd: st_spi_fsm: Supply all register address and bit logic defines Lee Jones
2014-01-08 13:46 ` [PATCH v4 03/37] mtd: st_spi_fsm: Initialise and configure the FSM for normal working conditions Lee Jones
2014-01-08 13:46 ` [PATCH v4 04/37] mtd: st_spi_fsm: Supply framework for device requests Lee Jones
2014-01-08 13:46 ` [PATCH v4 05/37] mtd: st_spi_fsm: Supply a method to read from the FSM's FIFO Lee Jones
2014-01-08 13:46 ` [PATCH v4 06/37] mtd: st_spi_fsm: Supply defines for the possible flash command opcodes Lee Jones
2014-01-08 13:46 ` [PATCH v4 07/37] mtd: st_spi_fsm: Add support for JEDEC ID extraction Lee Jones
2014-01-08 13:46 ` [PATCH v4 08/37] mtd: devices: Provide header for shared OPCODEs and SFDP commands Lee Jones
2014-01-08 13:46 ` [PATCH v4 09/37] mtd: st_spi_fsm: Provide device look-up table Lee Jones
2014-01-08 13:46 ` [PATCH v4 10/37] mtd: st_spi_fsm: Dynamically setup flash device based on JEDEC ID Lee Jones
2014-01-08 13:46 ` [PATCH v4 11/37] mtd: st_spi_fsm: Search for preferred FSM message sequence configurations Lee Jones
2014-01-08 13:46 ` [PATCH v4 12/37] mtd: st_spi_fsm: Fetch platform specific configurations Lee Jones
2014-01-08 13:46 ` [PATCH v4 13/37] mtd: st_spi_fsm: Prepare the read/write FSM message sequence(s) Lee Jones
2014-01-08 13:46 ` [PATCH v4 14/37] mtd: st_spi_fsm: Add device-tree binding documentation Lee Jones
2014-01-08 13:46 ` [PATCH v4 15/37] mtd: st_spi_fsm: Fetch boot-device from mode pins Lee Jones
2014-01-08 13:46 ` [PATCH v4 16/37] mtd: st_spi_fsm: Provide the erase one sector sequence Lee Jones
2014-01-08 13:47 ` [PATCH v4 17/37] mtd: st_spi_fsm: Provide the sequence for enabling 32bit addressing mode Lee Jones
2014-01-08 13:47 ` [PATCH v4 18/37] mtd: st_spi_fsm: Prepare read/write sequences according to configuration Lee Jones
2014-01-08 13:47 ` [PATCH v4 19/37] mtd: st_spi_fsm: Add a check to if the chip can handle an SoC reset Lee Jones
2014-01-08 13:47 ` [PATCH v4 20/37] mtd: st_spi_fsm: Provide a method to put the chip into 32bit addressing mode Lee Jones
2014-01-08 13:47 ` [PATCH v4 21/37] mtd: st_spi_fsm: Update the flash Volatile Configuration Register Lee Jones
2014-01-08 13:47 ` [PATCH v4 22/37] mtd: st_spi_fsm: Provide the default read/write configurations Lee Jones
2014-01-08 13:47 ` [PATCH v4 23/37] mtd: st_spi_fsm: Supply the N25Qxxx specific read configurations Lee Jones
2014-01-08 13:47 ` [PATCH v4 24/37] mtd: st_spi_fsm: Supply the N25Qxxx chip specific configuration call-back Lee Jones
2014-01-08 13:47 ` [PATCH v4 25/37] mtd: st_spi_fsm: Prepare default sequences for read/write/erase Lee Jones
2014-01-08 13:47 ` [PATCH v4 26/37] mtd: st_spi_fsm: Add the ability to read from a Serial Flash device Lee Jones
2014-01-08 13:47 ` [PATCH v4 27/37] mtd: st_spi_fsm: Write to Flash via the FSM FIFO Lee Jones
2014-01-08 13:47 ` [PATCH v4 28/37] mtd: st_spi_fsm: Supply a busy wait for post-write status Lee Jones
2014-01-08 13:47 ` Lee Jones [this message]
2014-01-08 13:47 ` [PATCH v4 30/37] mtd: st_spi_fsm: Erase partly or as a whole a Serial Flash device Lee Jones
2014-01-08 13:47 ` [PATCH v4 31/37] mtd: st_spi_fsm: Add the ability to read the FSM's status Lee Jones
2014-01-08 13:47 ` [PATCH v4 32/37] mtd: st_spi_fsm: Add the ability to write to FSM's status register Lee Jones
2014-01-08 13:47 ` [PATCH v4 33/37] mtd: st_spi_fsm: Supply the MX25xxx chip specific configuration call-back Lee Jones
2014-01-08 13:47 ` [PATCH v4 34/37] mtd: st_spi_fsm: Supply the S25FLxxx " Lee Jones
2014-01-08 13:47 ` [PATCH v4 35/37] mtd: st_spi_fsm: Supply the W25Qxxx " Lee Jones
2014-01-08 13:47 ` [PATCH v4 36/37] mtd: st_spi_fsm: Move runtime configurable msg sequences into device's struct Lee Jones
2014-01-08 13:47 ` [PATCH v4 37/37] ARM: STi: Add support for the FSM Serial Flash Controller Lee Jones
2014-01-08 14:33 ` [PATCH v4 00/36] mtd: st_spi_fsm: Add new driver Lee Jones
2014-01-22 12:50 ` Lee Jones
2014-01-23 1:46 ` Brian Norris
2014-02-24 11:39 ` Lee Jones
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=1389188840-14306-30-git-send-email-lee.jones@linaro.org \
--to=lee.jones@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/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;
as well as URLs for NNTP newsgroup(s).