summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: ff89f5d)
raw | patch | inline | side by side (parent: ff89f5d)
author | Ravikumar Kattekola <rk@ti.com> | |
Wed, 7 Aug 2013 12:38:32 +0000 (18:08 +0530) | ||
committer | Somnath Mukherjee <somnath@ti.com> | |
Thu, 8 Aug 2013 13:00:35 +0000 (18:30 +0530) |
Add Quad read mode (6 pin interface) support to spi flash
and ti qspi driver.
Quad mode (0x6bh on spansion) uses two extra pins (D2 and D3) for
data transfer apart from the usual D0 and D1 pins thus transfering
4 bits per cycle.
Signed-off-by: Ravikumar Kattekola <rk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
and ti qspi driver.
Quad mode (0x6bh on spansion) uses two extra pins (D2 and D3) for
data transfer apart from the usual D0 and D1 pins thus transfering
4 bits per cycle.
Signed-off-by: Ravikumar Kattekola <rk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
index e9e0b24f74d7552808e3bb949cfe77bea95015a3..76ac1fecfa593a1a983ee07d7f2de2c530b87781 100644 (file)
debug("SF: Failed to send command (%zu bytes): %d\n",
cmd_len, ret);
} else if (data_len != 0) {
- ret = spi_xfer(spi, data_len * 8, data_out, data_in, SPI_XFER_END);
+ if (spi->quad_enable)
+ flags = SPI_6WIRE;
+ else
+ flags = 0;
+
+ ret = spi_xfer(spi, data_len * 8, data_out, data_in, flags | SPI_XFER_END);
if (ret)
debug("SF: Failed to transfer %zu bytes of data: %d\n",
data_len, ret);
return ret;
}
+int spi_flash_cmd_read_quad(struct spi_flash *flash, u32 offset,
+ size_t len, void *data)
+{
+ struct spi_slave *spi = flash->spi;
+
+ unsigned long page_addr, byte_addr, page_size;
+ size_t chunk_len, actual;
+ int ret = 0;
+ u8 cmd[5];
+
+ spi->quad_enable = 1;
+ /* Handle memory-mapped SPI */
+ if (flash->memory_map)
+ memcpy(data, flash->memory_map + offset, len);
+
+ page_size = flash->page_size;
+ page_addr = offset / page_size;
+ byte_addr = offset % page_size;
+
+ cmd[0] = CMD_READ_ARRAY_QUAD;
+ for (actual = 0; actual < len; actual += chunk_len) {
+ chunk_len = min(len - actual, page_size - byte_addr);
+
+ cmd[1] = page_addr >> 8;
+ cmd[2] = page_addr;
+ cmd[3] = byte_addr;
+ cmd[4] = 0x0;
+
+ ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
+ data + actual, chunk_len);
+ if (ret < 0) {
+ debug("SF: read failed");
+ break;
+ }
+
+ byte_addr += chunk_len;
+ if (byte_addr == page_size) {
+ page_addr++;
+ byte_addr = 0;
+ }
+ }
+
+ return ret;
+}
+
int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
size_t len, void *data)
{
}
#endif
+int spi_flash_en_quad_mode(struct spi_flash *flash)
+{
+ u8 stat, con, cd;
+ u16 cr;
+ int ret;
+ cd = CMD_WRITE_STATUS;
+
+ ret = spi_flash_cmd_write_enable(flash);
+ if (ret < 0) {
+ debug("SF: enabling write failed\n");
+ goto out;
+ }
+ ret = spi_flash_cmd(flash->spi, CMD_READ_STATUS, &stat, 1);
+ ret = spi_flash_cmd(flash->spi, CMD_READ_CONFIG, &con, 1);
+ if (ret < 0) {
+ debug("%s: SF: read CR failed\n", __func__);
+ goto out;
+ }
+ /* Byte 1 - status reg, Byte 2 - config reg */
+ cr = ((con | (0x1 << 1)) << 8) | (stat << 0);
+
+ ret = spi_flash_cmd_write(flash->spi, &cd, 1, &cr, 2);
+ if (ret) {
+ debug("SF: fail to write conf register\n");
+ goto out;
+ }
+
+ ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+ if (ret < 0) {
+ debug("SF: write conf register timed out\n");
+ goto out;
+ }
+
+ ret = spi_flash_cmd(flash->spi, CMD_READ_STATUS, &stat, 1);
+ ret = spi_flash_cmd(flash->spi, CMD_READ_CONFIG, &con, 1);
+ if (ret < 0) {
+ debug("%s: SF: read CR failed\n", __func__);
+ goto out;
+ }
+ debug("%s: *** CR = %x\n", __func__, con);
+
+ ret = spi_flash_cmd_write_disable(flash);
+ if (ret < 0) {
+ debug("SF: disabling write failed\n");
+ goto out;
+ }
+out:
+ return ret;
+}
+
#ifdef CONFIG_OF_CONTROL
int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
{
goto err_manufacturer_probe;
#endif
+#ifdef CONFIG_SF_QUAD_RD
+ spi_flash_en_quad_mode(flash);
+#endif
+
#ifdef CONFIG_OF_CONTROL
if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
debug("SF: FDT decode error\n");
flash->name = name;
flash->poll_cmd = CMD_READ_STATUS;
+#ifdef CONFIG_SF_QUAD_RD
+ flash->read = spi_flash_cmd_read_quad;
+#else
flash->read = spi_flash_cmd_read_fast;
+#endif
flash->write = spi_flash_cmd_write_multi;
flash->erase = spi_flash_cmd_erase;
index be3c768c347e1bbfeb8f2f0ecff3081481182347..c791cbe64a7422b84dc6087898a1313ec01549a4 100644 (file)
#define CMD_READ_ARRAY_SLOW 0x03
#define CMD_READ_ARRAY_FAST 0x0b
+#define CMD_READ_ARRAY_QUAD 0x6b
#define CMD_WRITE_STATUS 0x01
#define CMD_PAGE_PROGRAM 0x02
#define CMD_WRITE_DISABLE 0x04
#define CMD_READ_STATUS 0x05
+#define CMD_READ_CONFIG 0x35
#define CMD_FLAG_STATUS 0x70
#define CMD_WRITE_ENABLE 0x06
#define CMD_ERASE_4K 0x20
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index 1973b85a447827cc08315450af8978442304acee..12bba11629036807a30f9c1a1a9e54087dc1bb94 100644 (file)
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
#define QSPI_RD_SNGL (1 << 16)
#define QSPI_WR_SNGL (2 << 16)
#define QSPI_INVAL (4 << 16)
+#define QSPI_RD_QUAD (7 << 16)
/* Device Control */
#define QSPI_DD(m, n) (m << (3 + n*8))
debug("tx done, status %08x\n", status);
}
if (rxp) {
- debug("rx cmd %08x dc %08x\n",
- qslave->cmd | QSPI_RD_SNGL, qslave->dc);
- writel(qslave->dc, &qspi->spi_dc);
- writel(qslave->cmd | QSPI_RD_SNGL, &qspi->spi_cmd);
+ if (flags & SPI_6WIRE) {
+ debug("rx cmd %08x dc %08x\n",
+ qslave->cmd | QSPI_RD_QUAD, qslave->dc);
+ writel(qslave->cmd | QSPI_RD_QUAD,
+ &qspi->spi_cmd);
+ } else {
+ debug("rx cmd %08x dc %08x\n",
+ qslave->cmd | QSPI_RD_SNGL, qslave->dc);
+ writel(qslave->cmd | QSPI_RD_SNGL,
+ &qspi->spi_cmd);
+ }
status = readl(&qspi->spi_status);
timeout = QSPI_TIMEOUT;
while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
}
*rxp++ = readl(&qspi->spi_data);
debug("rx done, status %08x, read %02x\n",
- status, *(rxp-1));
+ status, *(rxp-1));
}
}
index 7448e2b2d272e7415b9c8de44e4e2e4c51f5647c..d5cd451fdb75677307dd163fa4caeb45a77d3f59 100644 (file)
#define CONFIG_SPI_FLASH_SPANSION
#define CONFIG_CMD_SF
#define CONFIG_CMD_SPI
+#define CONFIG_SF_QUAD_RD
#define CONFIG_SF_DEFAULT_SPEED 12000000
#define CONFIG_DEFAULT_SPI_MODE SPI_MODE_3
diff --git a/include/spi.h b/include/spi.h
index 3fe2e1eab2defc568079cd8a035225bbf682b18d..c9277bf4d97358169bcb4ef119f621a43a391b10 100644 (file)
--- a/include/spi.h
+++ b/include/spi.h
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
#define SPI_LOOP 0x20 /* loopback mode */
+#define SPI_SLAVE 0x40 /* slave mode */
+#define SPI_PREAMBLE 0x80 /* Skip preamble bytes */
+#define SPI_6WIRE 0x10 /* 4 data lines */
/* SPI transfer flags */
#define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */
unsigned int bus;
unsigned int cs;
unsigned int max_write_size;
+ bool quad_enable;
};
/*-----------------------------------------------------------------------