All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support
@ 2014-05-06  1:13 Chao Fu
  2014-05-06  1:13 ` [U-Boot] [PATCH 2/3] arm: imx: Add two macros for VF610 in IOMUX_PAD structure Chao Fu
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Chao Fu @ 2014-05-06  1:13 UTC (permalink / raw)
  To: u-boot

From: Alison Wang <b18965@freescale.com>

Add Freescale QSPI driver support for VF610.

Signed-off-by: Alison Wang <Huan.Wang@freescale.com>
Signed-off-by: Chao Fu <b44548@freescale.com>
---
 drivers/spi/Makefile   |   1 +
 drivers/spi/fsl_qspi.c | 482 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/spi/fsl_qspi.h | 127 +++++++++++++
 3 files changed, 610 insertions(+)
 create mode 100644 drivers/spi/fsl_qspi.c
 create mode 100644 drivers/spi/fsl_qspi.h

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 81b6af6..b587308 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -40,3 +40,4 @@ obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
 obj-$(CONFIG_TI_QSPI) += ti_qspi.o
 obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
+obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
new file mode 100644
index 0000000..0dc09ca
--- /dev/null
+++ b/drivers/spi/fsl_qspi.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * Freescale Quad Serial Peripheral Interface (QSPI) driver
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+#include "fsl_qspi.h"
+
+#define RX_BUFFER_SIZE		0x80
+#define TX_BUFFER_SIZE		0x40
+
+#define OFFSET_BITS_MASK	0x00ffffff
+
+#define FLASH_STATUS_WEL	0x02
+
+/* SEQID */
+#define SEQID_WREN		1
+#define SEQID_FAST_READ		2
+#define SEQID_RDSR		3
+#define SEQID_SE		4
+#define SEQID_CHIP_ERASE	5
+#define SEQID_PP		6
+#define SEQID_RDID		7
+
+/* Flash opcodes */
+#define OPCODE_PP		0x02	/* Page program (up to 256 bytes) */
+#define OPCODE_RDSR		0x05	/* Read status register */
+#define OPCODE_WREN		0x06	/* Write enable */
+#define OPCODE_FAST_READ	0x0b	/* Read data bytes (high frequency) */
+#define OPCODE_CHIP_ERASE	0xc7	/* Erase whole flash chip */
+#define OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
+#define OPCODE_RDID		0x9f	/* Read JEDEC ID */
+
+/* 4-byte address opcodes - used on Spansion and some Macronix flashes */
+#define OPCODE_FAST_READ_4B	0x0c    /* Read data bytes (high frequency) */
+#define OPCODE_PP_4B		0x12    /* Page program (up to 256 bytes) */
+#define OPCODE_SE_4B		0xdc    /* Sector erase (usually 64KiB) */
+
+#ifdef CONFIG_SYS_FSL_QSPI_LE
+#define qspi_read32		in_le32
+#define qspi_write32		out_le32
+#elif defined(CONFIG_SYS_FSL_QSPI_BE)
+#define qspi_read32		in_be32
+#define qspi_write32		out_be32
+#endif
+
+static unsigned long spi_bases[] = {
+	QSPI0_BASE_ADDR,
+};
+
+static unsigned long amba_bases[] = {
+	QSPI0_AMBA_BASE,
+};
+
+struct fsl_qspi {
+	struct spi_slave slave;
+	unsigned long reg_base;
+	unsigned long amba_base;
+	u32 sf_addr;
+	u8 cur_seqid;
+};
+
+/* QSPI support swapping the flash read/write data
+ * in hardware for LS102xA, but not for VF610 */
+static inline u32 qspi_endian_xchg(u32 data)
+{
+#ifdef CONFIG_VF610
+	return swab32(data);
+#else
+	return data;
+#endif
+}
+
+static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct fsl_qspi, slave);
+}
+
+static void qspi_set_lut(struct fsl_qspi *qspi)
+{
+	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
+	u32 lut_base;
+
+	/* Unlock the LUT */
+	qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
+	qspi_write32(&regs->lckcr, QSPI_LCKCR_UNLOCK);
+
+	/* Write Enable */
+	lut_base = SEQID_WREN * 4;
+	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_WREN) |
+		PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
+	qspi_write32(&regs->lut[lut_base + 1], 0);
+	qspi_write32(&regs->lut[lut_base + 2], 0);
+	qspi_write32(&regs->lut[lut_base + 3], 0);
+
+	/* Fast Read */
+	lut_base = SEQID_FAST_READ * 4;
+	if (FSL_QSPI_FLASH_SIZE  <= SZ_16M)
+		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_FAST_READ) |
+			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	else
+		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_FAST_READ_4B) |
+			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
+			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	qspi_write32(&regs->lut[lut_base + 1], OPRND0(8) | PAD0(LUT_PAD1) |
+		INSTR0(LUT_DUMMY) | OPRND1(RX_BUFFER_SIZE) | PAD1(LUT_PAD1) |
+		INSTR1(LUT_READ));
+	qspi_write32(&regs->lut[lut_base + 2], 0);
+	qspi_write32(&regs->lut[lut_base + 3], 0);
+
+	/* Read Status */
+	lut_base = SEQID_RDSR * 4;
+	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_RDSR) |
+		PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
+		PAD1(LUT_PAD1) | INSTR1(LUT_READ));
+	qspi_write32(&regs->lut[lut_base + 1], 0);
+	qspi_write32(&regs->lut[lut_base + 2], 0);
+	qspi_write32(&regs->lut[lut_base + 3], 0);
+
+	/* Erase a sector */
+	lut_base = SEQID_SE * 4;
+	if (FSL_QSPI_FLASH_SIZE  <= SZ_16M)
+		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_SE) |
+			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	else
+		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_SE_4B) |
+			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
+			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	qspi_write32(&regs->lut[lut_base + 1], 0);
+	qspi_write32(&regs->lut[lut_base + 2], 0);
+	qspi_write32(&regs->lut[lut_base + 3], 0);
+
+	/* Erase the whole chip */
+	lut_base = SEQID_CHIP_ERASE * 4;
+	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_CHIP_ERASE) |
+		PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
+	qspi_write32(&regs->lut[lut_base + 1], 0);
+	qspi_write32(&regs->lut[lut_base + 2], 0);
+	qspi_write32(&regs->lut[lut_base + 3], 0);
+
+	/* Page Program */
+	lut_base = SEQID_PP * 4;
+	if (FSL_QSPI_FLASH_SIZE  <= SZ_16M)
+		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_PP) |
+			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	else
+		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_PP_4B) |
+			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
+			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+	qspi_write32(&regs->lut[lut_base + 1], OPRND0(TX_BUFFER_SIZE) |
+		PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
+	qspi_write32(&regs->lut[lut_base + 2], 0);
+	qspi_write32(&regs->lut[lut_base + 3], 0);
+
+	/* READ ID */
+	lut_base = SEQID_RDID * 4;
+	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_RDID) |
+		PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(8) |
+		PAD1(LUT_PAD1) | INSTR1(LUT_READ));
+	qspi_write32(&regs->lut[lut_base + 1], 0);
+	qspi_write32(&regs->lut[lut_base + 2], 0);
+	qspi_write32(&regs->lut[lut_base + 3], 0);
+
+	/* Lock the LUT */
+	qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
+	qspi_write32(&regs->lckcr, QSPI_LCKCR_LOCK);
+}
+
+void spi_init()
+{
+	/* do nothing */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	struct fsl_qspi *qspi;
+	struct fsl_qspi_regs *regs;
+	u32 reg_val, smpr_val;
+	u32 total_size, seq_id;
+
+	if (bus >= ARRAY_SIZE(spi_bases))
+		return NULL;
+
+	qspi = spi_alloc_slave(struct fsl_qspi, bus, cs);
+	if (!qspi)
+		return NULL;
+
+	qspi->reg_base = spi_bases[bus];
+	qspi->amba_base = amba_bases[bus];
+
+	qspi->slave.max_write_size = TX_BUFFER_SIZE;
+
+	regs = (struct fsl_qspi_regs *)qspi->reg_base;
+	qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
+
+	smpr_val = qspi_read32(&regs->smpr);
+	qspi_write32(&regs->smpr, smpr_val & ~(QSPI_SMPR_FSDLY_MASK |
+		QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK));
+	qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
+
+	total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
+	qspi_write32(&regs->sfa1ad, FSL_QSPI_FLASH_SIZE | qspi->amba_base);
+	qspi_write32(&regs->sfa2ad, FSL_QSPI_FLASH_SIZE | qspi->amba_base);
+	qspi_write32(&regs->sfb1ad, total_size | qspi->amba_base);
+	qspi_write32(&regs->sfb2ad, total_size | qspi->amba_base);
+
+	qspi_set_lut(qspi);
+
+	smpr_val = qspi_read32(&regs->smpr);
+	smpr_val &= ~QSPI_SMPR_DDRSMP_MASK;
+	qspi_write32(&regs->smpr, smpr_val);
+	qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
+
+	seq_id = 0;
+	reg_val = qspi_read32(&regs->bfgencr);
+	reg_val &= ~QSPI_BFGENCR_SEQID_MASK;
+	reg_val |= (seq_id << QSPI_BFGENCR_SEQID_SHIFT);
+	reg_val &= ~QSPI_BFGENCR_PAR_EN_MASK;
+	qspi_write32(&regs->bfgencr, reg_val);
+
+	return &qspi->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct fsl_qspi *qspi = to_qspi_spi(slave);
+
+	free(qspi);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	return 0;
+}
+
+static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
+{
+	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
+	u32 mcr_reg, rbsr_reg, data;
+	int i, size;
+
+	mcr_reg = qspi_read32(&regs->mcr);
+	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
+		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
+
+	qspi_write32(&regs->sfar, qspi->amba_base);
+
+	qspi_write32(&regs->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0);
+	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+		;
+
+	i = 0;
+	size = len;
+	while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
+		rbsr_reg = qspi_read32(&regs->rbsr);
+		if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
+			data = qspi_read32(&regs->rbdr[i]);
+			data = qspi_endian_xchg(data);
+			memcpy(rxbuf, &data, 4);
+			rxbuf++;
+			size -= 4;
+			i++;
+		}
+	}
+
+	qspi_write32(&regs->mcr, mcr_reg);
+}
+
+static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
+{
+	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
+	u32 mcr_reg, data;
+	int i, size;
+	u32 to_or_from;
+
+	mcr_reg = qspi_read32(&regs->mcr);
+	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
+		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
+
+	to_or_from = qspi->sf_addr + qspi->amba_base;
+
+	while (len > 0) {
+		qspi_write32(&regs->sfar, to_or_from);
+
+		size = (len > RX_BUFFER_SIZE) ?
+			RX_BUFFER_SIZE : len;
+
+		qspi_write32(&regs->ipcr,
+			(SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) | size);
+		while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+			;
+
+		to_or_from += size;
+		len -= size;
+
+		i = 0;
+		while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
+			data = qspi_read32(&regs->rbdr[i]);
+			data = qspi_endian_xchg(data);
+			memcpy(rxbuf, &data, 4);
+			rxbuf++;
+			size -= 4;
+			i++;
+		}
+		qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
+			QSPI_MCR_CLR_RXF_MASK);
+	}
+
+	qspi_write32(&regs->mcr, mcr_reg);
+}
+
+static void qspi_op_pp(struct fsl_qspi *qspi, u32 *txbuf, u32 len)
+{
+	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
+	u32 mcr_reg, data, reg, status_reg;
+	int i, size, tx_size;
+	u32 to_or_from = 0;
+
+	mcr_reg = qspi_read32(&regs->mcr);
+	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
+		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
+
+	status_reg = 0;
+	while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) {
+		qspi_write32(&regs->ipcr,
+			(SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
+		while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+			;
+
+		qspi_write32(&regs->ipcr,
+			(SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
+		while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+			;
+
+		reg = qspi_read32(&regs->rbsr);
+		if (reg & QSPI_RBSR_RDBFL_MASK) {
+			status_reg = qspi_read32(&regs->rbdr[0]);
+			status_reg = qspi_endian_xchg(status_reg);
+		}
+		qspi_write32(&regs->mcr,
+			qspi_read32(&regs->mcr) | QSPI_MCR_CLR_RXF_MASK);
+	}
+
+	to_or_from = qspi->sf_addr + qspi->amba_base;
+	qspi_write32(&regs->sfar, to_or_from);
+
+	tx_size = (len > TX_BUFFER_SIZE) ?
+		TX_BUFFER_SIZE : len;
+
+	size = (tx_size + 3) / 4;
+
+	for (i = 0; i < size; i++) {
+		data = qspi_endian_xchg(*txbuf);
+		qspi_write32(&regs->tbdr, data);
+		txbuf++;
+	}
+
+	qspi_write32(&regs->ipcr,
+		(SEQID_PP << QSPI_IPCR_SEQID_SHIFT) | tx_size);
+	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+		;
+
+	qspi_write32(&regs->mcr, mcr_reg);
+}
+
+static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf)
+{
+	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
+	u32 mcr_reg, reg, data;
+
+	mcr_reg = qspi_read32(&regs->mcr);
+	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
+		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
+
+	qspi_write32(&regs->sfar, qspi->amba_base);
+
+	qspi_write32(&regs->ipcr,
+		(SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0);
+	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+		;
+
+	while (1) {
+		reg = qspi_read32(&regs->rbsr);
+		if (reg & QSPI_RBSR_RDBFL_MASK) {
+			data = qspi_read32(&regs->rbdr[0]);
+			data = qspi_endian_xchg(data);
+			memcpy(rxbuf, &data, 4);
+			qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
+				QSPI_MCR_CLR_RXF_MASK);
+			break;
+		}
+	}
+
+	qspi_write32(&regs->mcr, mcr_reg);
+}
+
+static void qspi_op_se(struct fsl_qspi *qspi)
+{
+	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
+	u32 mcr_reg;
+	u32 to_or_from = 0;
+
+	mcr_reg = qspi_read32(&regs->mcr);
+	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
+		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
+
+	to_or_from = qspi->sf_addr + qspi->amba_base;
+	qspi_write32(&regs->sfar, to_or_from);
+
+	qspi_write32(&regs->ipcr,
+		(SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
+	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+		;
+
+	qspi_write32(&regs->ipcr,
+		(SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0);
+	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+		;
+
+	qspi_write32(&regs->mcr, mcr_reg);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct fsl_qspi *qspi = to_qspi_spi(slave);
+	u32 bytes = DIV_ROUND_UP(bitlen, 8);
+	static u32 pp_sfaddr;
+	u32 txbuf;
+
+	if (dout) {
+		memcpy(&txbuf, dout, 4);
+		qspi->cur_seqid = *(u8 *)dout;
+
+		if (flags == SPI_XFER_END) {
+			qspi->sf_addr = pp_sfaddr;
+			qspi_op_pp(qspi, (u32 *)dout, bytes);
+			return 0;
+		}
+
+		if (qspi->cur_seqid == OPCODE_FAST_READ) {
+			qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
+		} else if (qspi->cur_seqid == OPCODE_SE) {
+			qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
+			qspi_op_se(qspi);
+		} else if (qspi->cur_seqid == OPCODE_PP) {
+			pp_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
+		}
+	}
+
+	if (din) {
+		if (qspi->cur_seqid == OPCODE_FAST_READ)
+			qspi_op_read(qspi, din, bytes);
+		else if (qspi->cur_seqid == OPCODE_RDID)
+			qspi_op_rdid(qspi, din, bytes);
+		else if (qspi->cur_seqid == OPCODE_RDSR)
+			qspi_op_rdsr(qspi, din);
+	}
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	/* Nothing to do */
+}
diff --git a/drivers/spi/fsl_qspi.h b/drivers/spi/fsl_qspi.h
new file mode 100644
index 0000000..db400e6
--- /dev/null
+++ b/drivers/spi/fsl_qspi.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * Register definitions for Freescale QSPI
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _FSL_QSPI_H_
+#define _FSL_QSPI_H_
+
+struct fsl_qspi_regs {
+	u32 mcr;
+	u32 rsvd0[1];
+	u32 ipcr;
+	u32 flshcr;
+	u32 buf0cr;
+	u32 buf1cr;
+	u32 buf2cr;
+	u32 buf3cr;
+	u32 bfgencr;
+	u32 soccr;
+	u32 rsvd1[2];
+	u32 buf0ind;
+	u32 buf1ind;
+	u32 buf2ind;
+	u32 rsvd2[49];
+	u32 sfar;
+	u32 rsvd3[1];
+	u32 smpr;
+	u32 rbsr;
+	u32 rbct;
+	u32 rsvd4[15];
+	u32 tbsr;
+	u32 tbdr;
+	u32 rsvd5[1];
+	u32 sr;
+	u32 fr;
+	u32 rser;
+	u32 spndst;
+	u32 sptrclr;
+	u32 rsvd6[4];
+	u32 sfa1ad;
+	u32 sfa2ad;
+	u32 sfb1ad;
+	u32 sfb2ad;
+	u32 rsvd7[28];
+	u32 rbdr[32];
+	u32 rsvd8[32];
+	u32 lutkey;
+	u32 lckcr;
+	u32 rsvd9[2];
+	u32 lut[64];
+};
+
+#define QSPI_IPCR_SEQID_SHIFT		24
+#define QSPI_IPCR_SEQID_MASK		(0xf << QSPI_IPCR_SEQID_SHIFT)
+
+#define QSPI_MCR_END_CFD_SHIFT		2
+#define QSPI_MCR_END_CFD_MASK		(3 << QSPI_MCR_END_CFD_SHIFT)
+#define QSPI_MCR_END_CFD_LE		(1 << QSPI_MCR_END_CFD_SHIFT)
+#define QSPI_MCR_DDR_EN_SHIFT		7
+#define QSPI_MCR_DDR_EN_MASK		(1 << QSPI_MCR_DDR_EN_SHIFT)
+#define QSPI_MCR_CLR_RXF_SHIFT		10
+#define QSPI_MCR_CLR_RXF_MASK		(1 << QSPI_MCR_CLR_RXF_SHIFT)
+#define QSPI_MCR_CLR_TXF_SHIFT		11
+#define QSPI_MCR_CLR_TXF_MASK		(1 << QSPI_MCR_CLR_TXF_SHIFT)
+#define QSPI_MCR_MDIS_SHIFT		14
+#define QSPI_MCR_MDIS_MASK		(1 << QSPI_MCR_MDIS_SHIFT)
+#define QSPI_MCR_RESERVED_SHIFT		16
+#define QSPI_MCR_RESERVED_MASK		(0xf << QSPI_MCR_RESERVED_SHIFT)
+
+#define QSPI_SMPR_HSENA_SHIFT		0
+#define QSPI_SMPR_HSENA_MASK		(1 << QSPI_SMPR_HSENA_SHIFT)
+#define QSPI_SMPR_FSPHS_SHIFT		5
+#define QSPI_SMPR_FSPHS_MASK		(1 << QSPI_SMPR_FSPHS_SHIFT)
+#define QSPI_SMPR_FSDLY_SHIFT		6
+#define QSPI_SMPR_FSDLY_MASK		(1 << QSPI_SMPR_FSDLY_SHIFT)
+#define QSPI_SMPR_DDRSMP_SHIFT		16
+#define QSPI_SMPR_DDRSMP_MASK		(7 << QSPI_SMPR_DDRSMP_SHIFT)
+
+#define QSPI_BFGENCR_SEQID_SHIFT	12
+#define QSPI_BFGENCR_SEQID_MASK		(0xf << QSPI_BFGENCR_SEQID_SHIFT)
+#define QSPI_BFGENCR_PAR_EN_SHIFT	16
+#define QSPI_BFGENCR_PAR_EN_MASK	(1 << QSPI_BFGENCR_PAR_EN_SHIFT)
+
+#define QSPI_RBSR_RDBFL_SHIFT		8
+#define QSPI_RBSR_RDBFL_MASK		(0x3f << QSPI_RBSR_RDBFL_SHIFT)
+
+#define QSPI_RBCT_RXBRD_SHIFT		8
+#define QSPI_RBCT_RXBRD_USEIPS		(1 << QSPI_RBCT_RXBRD_SHIFT)
+
+#define QSPI_SR_BUSY_SHIFT		0
+#define QSPI_SR_BUSY_MASK		(1 << QSPI_SR_BUSY_SHIFT)
+
+#define QSPI_LCKCR_LOCK			0x1
+#define QSPI_LCKCR_UNLOCK		0x2
+
+#define LUT_KEY_VALUE			0x5af05af0
+
+#define OPRND0_SHIFT			0
+#define OPRND0(x)			((x) << OPRND0_SHIFT)
+#define PAD0_SHIFT			8
+#define PAD0(x)				((x) << PAD0_SHIFT)
+#define INSTR0_SHIFT			10
+#define INSTR0(x)			((x) << INSTR0_SHIFT)
+#define OPRND1_SHIFT			16
+#define OPRND1(x)			((x) << OPRND1_SHIFT)
+#define PAD1_SHIFT			24
+#define PAD1(x)				((x) << PAD1_SHIFT)
+#define INSTR1_SHIFT			26
+#define INSTR1(x)			((x) << INSTR1_SHIFT)
+
+#define LUT_CMD				1
+#define LUT_ADDR			2
+#define LUT_DUMMY			3
+#define LUT_READ			7
+#define LUT_WRITE			8
+
+#define LUT_PAD1			0
+#define LUT_PAD2			1
+#define LUT_PAD4			2
+
+#define ADDR24BIT			0x18
+#define ADDR32BIT			0x20
+
+#endif /* _FSL_QSPI_H_ */
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH 2/3] arm: imx: Add two macros for VF610 in IOMUX_PAD structure
  2014-05-06  1:13 [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support Chao Fu
@ 2014-05-06  1:13 ` Chao Fu
  2014-05-06  1:13 ` [U-Boot] [PATCH 3/3] arm: vf610: Add QSPI support for VF610TWR Chao Fu
  2014-06-09  8:09 ` [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support Albert ARIBAUD
  2 siblings, 0 replies; 4+ messages in thread
From: Chao Fu @ 2014-05-06  1:13 UTC (permalink / raw)
  To: u-boot

From: Alison Wang <b18965@freescale.com>

Add PAD_CTL_DSE_150ohm and PAD_CTL_PUS_22K_UP for VF610 in
IOMUX_PAD structure.

Signed-off-by: Alison Wang <Huan.Wang@freescale.com>
---
 arch/arm/include/asm/imx-common/iomux-v3.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/include/asm/imx-common/iomux-v3.h b/arch/arm/include/asm/imx-common/iomux-v3.h
index dec11a1..017a1f0 100644
--- a/arch/arm/include/asm/imx-common/iomux-v3.h
+++ b/arch/arm/include/asm/imx-common/iomux-v3.h
@@ -118,12 +118,14 @@ typedef u64 iomux_v3_cfg_t;
 #define PAD_CTL_SPEED_MED	(1 << 12)
 #define PAD_CTL_SPEED_HIGH	(3 << 12)
 
+#define PAD_CTL_DSE_150ohm	(1 << 6)
 #define PAD_CTL_DSE_50ohm	(3 << 6)
 #define PAD_CTL_DSE_25ohm	(6 << 6)
 #define PAD_CTL_DSE_20ohm	(7 << 6)
 
 #define PAD_CTL_PUS_47K_UP	(1 << 4 | PAD_CTL_PUE)
 #define PAD_CTL_PUS_100K_UP	(2 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_22K_UP	(3 << 4 | PAD_CTL_PUE)
 #define PAD_CTL_PKE		(1 << 3)
 #define PAD_CTL_PUE		(1 << 2 | PAD_CTL_PKE)
 
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH 3/3] arm: vf610: Add QSPI support for VF610TWR
  2014-05-06  1:13 [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support Chao Fu
  2014-05-06  1:13 ` [U-Boot] [PATCH 2/3] arm: imx: Add two macros for VF610 in IOMUX_PAD structure Chao Fu
@ 2014-05-06  1:13 ` Chao Fu
  2014-06-09  8:09 ` [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support Albert ARIBAUD
  2 siblings, 0 replies; 4+ messages in thread
From: Chao Fu @ 2014-05-06  1:13 UTC (permalink / raw)
  To: u-boot

From: Chao Fu <B44548@freescale.com>

Add QSPI support for VF610TWR, such as clock and iomux.

Signed-off-by: Alison Wang <Huan.Wang@freescale.com>
Signed-off-by: Chao Fu <b44548@freescale.com>
---
 arch/arm/include/asm/arch-vf610/crm_regs.h    | 11 +++++++++-
 arch/arm/include/asm/arch-vf610/imx-regs.h    |  4 +++-
 arch/arm/include/asm/arch-vf610/iomux-vf610.h | 17 +++++++++++++++-
 board/freescale/vf610twr/vf610twr.c           | 29 +++++++++++++++++++++++++--
 include/configs/vf610twr.h                    | 12 +++++++++++
 5 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/arch-vf610/crm_regs.h b/arch/arm/include/asm/arch-vf610/crm_regs.h
index e17c7d1..5256624 100644
--- a/arch/arm/include/asm/arch-vf610/crm_regs.h
+++ b/arch/arm/include/asm/arch-vf610/crm_regs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -150,6 +150,9 @@ struct anadig_reg {
 #define CCM_CACRR_ARM_CLK_DIV_MASK		0x7
 #define CCM_CACRR_ARM_CLK_DIV(v)		((v) & 0x7)
 
+#define CCM_CSCMR1_QSPI0_CLK_SEL_OFFSET		22
+#define CCM_CSCMR1_QSPI0_CLK_SEL_MASK		(0x3 << 22)
+#define CCM_CSCMR1_QSPI0_CLK_SEL(v)		(((v) & 0x3) << 22)
 #define CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET	18
 #define CCM_CSCMR1_ESDHC1_CLK_SEL_MASK		(0x3 << 18)
 #define CCM_CSCMR1_ESDHC1_CLK_SEL(v)		(((v) & 0x3) << 18)
@@ -161,6 +164,11 @@ struct anadig_reg {
 #define CCM_CSCDR2_ESDHC1_CLK_DIV_MASK		(0xf << 20)
 #define CCM_CSCDR2_ESDHC1_CLK_DIV(v)		(((v) & 0xf) << 20)
 
+#define CCM_CSCDR3_QSPI0_EN			(1 << 4)
+#define CCM_CSCDR3_QSPI0_DIV(v)			((v) << 3)
+#define CCM_CSCDR3_QSPI0_X2_DIV(v)		((v) << 2)
+#define CCM_CSCDR3_QSPI0_X4_DIV(v)		((v) & 0x3)
+
 #define CCM_CSCMR2_RMII_CLK_SEL_OFFSET		4
 #define CCM_CSCMR2_RMII_CLK_SEL_MASK		(0x3 << 4)
 #define CCM_CSCMR2_RMII_CLK_SEL(v)		(((v) & 0x3) << 4)
@@ -170,6 +178,7 @@ struct anadig_reg {
 #define CCM_CCGR0_UART1_CTRL_MASK		(0x3 << 16)
 #define CCM_CCGR1_PIT_CTRL_MASK			(0x3 << 14)
 #define CCM_CCGR1_WDOGA5_CTRL_MASK		(0x3 << 28)
+#define CCM_CCGR2_QSPI0_CTRL_MASK		(0x3 << 8)
 #define CCM_CCGR2_IOMUXC_CTRL_MASK		(0x3 << 16)
 #define CCM_CCGR2_PORTA_CTRL_MASK		(0x3 << 18)
 #define CCM_CCGR2_PORTB_CTRL_MASK		(0x3 << 20)
diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h
index c2f9761..40d7d9d 100644
--- a/arch/arm/include/asm/arch-vf610/imx-regs.h
+++ b/arch/arm/include/asm/arch-vf610/imx-regs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -87,6 +87,8 @@
 #define ENET_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00050000)
 #define ENET1_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00051000)
 
+#define QSPI0_AMBA_BASE		0x20000000
+
 /* MUX mode and PAD ctrl are in one register */
 #define CONFIG_IOMUX_SHARE_CONF_REG
 
diff --git a/arch/arm/include/asm/arch-vf610/iomux-vf610.h b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
index 88807d8..a965641 100644
--- a/arch/arm/include/asm/arch-vf610/iomux-vf610.h
+++ b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -20,6 +20,9 @@
 #define VF610_I2C_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_50ohm | \
 				PAD_CTL_SPEED_HIGH | PAD_CTL_OBE_IBE_ENABLE)
 
+#define VF610_QSPI_PAD_CTRL	(PAD_CTL_SPEED_HIGH | PAD_CTL_DSE_150ohm | \
+				PAD_CTL_PUS_22K_UP | PAD_CTL_OBE_IBE_ENABLE)
+
 enum {
 	VF610_PAD_PTA6__RMII0_CLKIN		= IOMUX_PAD(0x0000, 0x0000, 2, __NA_, 0, VF610_ENET_PAD_CTRL),
 	VF610_PAD_PTA6__RMII0_CLKOUT		= IOMUX_PAD(0x0000, 0x0000, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
@@ -53,6 +56,18 @@ enum {
 	VF610_PAD_PTA29__ESDHC1_DAT3		= IOMUX_PAD(0x004c, 0x004c, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
 	VF610_PAD_PTB14__I2C0_SCL		= IOMUX_PAD(0x0090, 0x0090, 2, 0x033c, 1, VF610_I2C_PAD_CTRL),
 	VF610_PAD_PTB15__I2C0_SDA		= IOMUX_PAD(0x0094, 0x0094, 2, 0x0340, 1, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTD0__QSPI0_A_QSCK		= IOMUX_PAD(0x013c, 0x013c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD1__QSPI0_A_CS0		= IOMUX_PAD(0x0140, 0x0140, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD2__QSPI0_A_DATA3		= IOMUX_PAD(0x0144, 0x0144, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD3__QSPI0_A_DATA2		= IOMUX_PAD(0x0148, 0x0148, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD4__QSPI0_A_DATA1		= IOMUX_PAD(0x014c, 0x014c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD5__QSPI0_A_DATA0		= IOMUX_PAD(0x0150, 0x0150, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD7__QSPI0_B_QSCK		= IOMUX_PAD(0x0158, 0x0158, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD8__QSPI0_B_CS0		= IOMUX_PAD(0x015c, 0x015c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD9__QSPI0_B_DATA3		= IOMUX_PAD(0x0160, 0x0160, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD10__QSPI0_B_DATA2		= IOMUX_PAD(0x0164, 0x0164, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD11__QSPI0_B_DATA1		= IOMUX_PAD(0x0168, 0x0168, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD12__QSPI0_B_DATA0		= IOMUX_PAD(0x016c, 0x016c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
 	VF610_PAD_DDR_A15__DDR_A_15		= IOMUX_PAD(0x0220, 0x0220, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
 	VF610_PAD_DDR_A14__DDR_A_14		= IOMUX_PAD(0x0224, 0x0224, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
 	VF610_PAD_DDR_A13__DDR_A_13		= IOMUX_PAD(0x0228, 0x0228, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
diff --git a/board/freescale/vf610twr/vf610twr.c b/board/freescale/vf610twr/vf610twr.c
index 4ee74c0..03c1f16 100644
--- a/board/freescale/vf610twr/vf610twr.c
+++ b/board/freescale/vf610twr/vf610twr.c
@@ -277,6 +277,26 @@ static void setup_iomux_i2c(void)
 	imx_iomux_v3_setup_multiple_pads(i2c0_pads, ARRAY_SIZE(i2c0_pads));
 }
 
+static void setup_iomux_qspi(void)
+{
+	static const iomux_v3_cfg_t qspi0_pads[] = {
+		VF610_PAD_PTD0__QSPI0_A_QSCK,
+		VF610_PAD_PTD1__QSPI0_A_CS0,
+		VF610_PAD_PTD2__QSPI0_A_DATA3,
+		VF610_PAD_PTD3__QSPI0_A_DATA2,
+		VF610_PAD_PTD4__QSPI0_A_DATA1,
+		VF610_PAD_PTD5__QSPI0_A_DATA0,
+		VF610_PAD_PTD7__QSPI0_B_QSCK,
+		VF610_PAD_PTD8__QSPI0_B_CS0,
+		VF610_PAD_PTD9__QSPI0_B_DATA3,
+		VF610_PAD_PTD10__QSPI0_B_DATA2,
+		VF610_PAD_PTD11__QSPI0_B_DATA1,
+		VF610_PAD_PTD12__QSPI0_B_DATA0,
+	};
+
+	imx_iomux_v3_setup_multiple_pads(qspi0_pads, ARRAY_SIZE(qspi0_pads));
+}
+
 #ifdef CONFIG_FSL_ESDHC
 struct fsl_esdhc_cfg esdhc_cfg[1] = {
 	{ESDHC1_BASE_ADDR},
@@ -320,7 +340,8 @@ static void clock_init(void)
 	clrsetbits_le32(&ccm->ccgr2, CCM_REG_CTRL_MASK,
 		CCM_CCGR2_IOMUXC_CTRL_MASK | CCM_CCGR2_PORTA_CTRL_MASK |
 		CCM_CCGR2_PORTB_CTRL_MASK | CCM_CCGR2_PORTC_CTRL_MASK |
-		CCM_CCGR2_PORTD_CTRL_MASK | CCM_CCGR2_PORTE_CTRL_MASK);
+		CCM_CCGR2_PORTD_CTRL_MASK | CCM_CCGR2_PORTE_CTRL_MASK |
+		CCM_CCGR2_QSPI0_CTRL_MASK);
 	clrsetbits_le32(&ccm->ccgr3, CCM_REG_CTRL_MASK,
 		CCM_CCGR3_ANADIG_CTRL_MASK);
 	clrsetbits_le32(&ccm->ccgr4, CCM_REG_CTRL_MASK,
@@ -351,11 +372,14 @@ static void clock_init(void)
 		CCM_CACRR_IPG_CLK_DIV(1) | CCM_CACRR_BUS_CLK_DIV(2) |
 		CCM_CACRR_ARM_CLK_DIV(0));
 	clrsetbits_le32(&ccm->cscmr1, CCM_REG_CTRL_MASK,
-		CCM_CSCMR1_ESDHC1_CLK_SEL(3));
+		CCM_CSCMR1_ESDHC1_CLK_SEL(3) | CCM_CSCMR1_QSPI0_CLK_SEL(3));
 	clrsetbits_le32(&ccm->cscdr1, CCM_REG_CTRL_MASK,
 		CCM_CSCDR1_RMII_CLK_EN);
 	clrsetbits_le32(&ccm->cscdr2, CCM_REG_CTRL_MASK,
 		CCM_CSCDR2_ESDHC1_EN | CCM_CSCDR2_ESDHC1_CLK_DIV(0));
+	clrsetbits_le32(&ccm->cscdr3, CCM_REG_CTRL_MASK,
+		CCM_CSCDR3_QSPI0_EN | CCM_CSCDR3_QSPI0_DIV(1) |
+		CCM_CSCDR3_QSPI0_X2_DIV(1) | CCM_CSCDR3_QSPI0_X4_DIV(3));
 	clrsetbits_le32(&ccm->cscmr2, CCM_REG_CTRL_MASK,
 		CCM_CSCMR2_RMII_CLK_SEL(0));
 }
@@ -385,6 +409,7 @@ int board_early_init_f(void)
 	setup_iomux_uart();
 	setup_iomux_enet();
 	setup_iomux_i2c();
+	setup_iomux_qspi();
 
 	return 0;
 }
diff --git a/include/configs/vf610twr.h b/include/configs/vf610twr.h
index 500fd2f..0342550 100644
--- a/include/configs/vf610twr.h
+++ b/include/configs/vf610twr.h
@@ -68,6 +68,18 @@
 #define CONFIG_PHYLIB
 #define CONFIG_PHY_MICREL
 
+/* QSPI Configs*/
+#define CONFIG_FSL_QSPI
+
+#ifdef CONFIG_FSL_QSPI
+#define CONFIG_CMD_SF
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_SPANSION
+#define FSL_QSPI_FLASH_SIZE		(1 << 24)
+#define FSL_QSPI_FLASH_NUM		2
+#define CONFIG_SYS_FSL_QSPI_LE
+#endif
+
 /* I2C Configs */
 #define CONFIG_CMD_I2C
 #define CONFIG_SYS_I2C
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support
  2014-05-06  1:13 [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support Chao Fu
  2014-05-06  1:13 ` [U-Boot] [PATCH 2/3] arm: imx: Add two macros for VF610 in IOMUX_PAD structure Chao Fu
  2014-05-06  1:13 ` [U-Boot] [PATCH 3/3] arm: vf610: Add QSPI support for VF610TWR Chao Fu
@ 2014-06-09  8:09 ` Albert ARIBAUD
  2 siblings, 0 replies; 4+ messages in thread
From: Albert ARIBAUD @ 2014-06-09  8:09 UTC (permalink / raw)
  To: u-boot

Hi Chao,

On Tue, 6 May 2014 09:13:01 +0800, Chao Fu <b44548@freescale.com> wrote:

> From: Alison Wang <b18965@freescale.com>
> 
> Add Freescale QSPI driver support for VF610.
> 
> Signed-off-by: Alison Wang <Huan.Wang@freescale.com>
> Signed-off-by: Chao Fu <b44548@freescale.com>
> ---
>  drivers/spi/Makefile   |   1 +
>  drivers/spi/fsl_qspi.c | 482 +++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/spi/fsl_qspi.h | 127 +++++++++++++
>  3 files changed, 610 insertions(+)
>  create mode 100644 drivers/spi/fsl_qspi.c
>  create mode 100644 drivers/spi/fsl_qspi.h
> 
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 81b6af6..b587308 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -40,3 +40,4 @@ obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
>  obj-$(CONFIG_TI_QSPI) += ti_qspi.o
>  obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
>  obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
> +obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
> diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
> new file mode 100644
> index 0000000..0dc09ca
> --- /dev/null
> +++ b/drivers/spi/fsl_qspi.c
> @@ -0,0 +1,482 @@
> +/*
> + * Copyright 2013-2014 Freescale Semiconductor, Inc.
> + *
> + * Freescale Quad Serial Peripheral Interface (QSPI) driver
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <asm/io.h>
> +#include <linux/sizes.h>
> +#include "fsl_qspi.h"
> +
> +#define RX_BUFFER_SIZE		0x80
> +#define TX_BUFFER_SIZE		0x40
> +
> +#define OFFSET_BITS_MASK	0x00ffffff
> +
> +#define FLASH_STATUS_WEL	0x02
> +
> +/* SEQID */
> +#define SEQID_WREN		1
> +#define SEQID_FAST_READ		2
> +#define SEQID_RDSR		3
> +#define SEQID_SE		4
> +#define SEQID_CHIP_ERASE	5
> +#define SEQID_PP		6
> +#define SEQID_RDID		7
> +
> +/* Flash opcodes */
> +#define OPCODE_PP		0x02	/* Page program (up to 256 bytes) */
> +#define OPCODE_RDSR		0x05	/* Read status register */
> +#define OPCODE_WREN		0x06	/* Write enable */
> +#define OPCODE_FAST_READ	0x0b	/* Read data bytes (high frequency) */
> +#define OPCODE_CHIP_ERASE	0xc7	/* Erase whole flash chip */
> +#define OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
> +#define OPCODE_RDID		0x9f	/* Read JEDEC ID */
> +
> +/* 4-byte address opcodes - used on Spansion and some Macronix flashes */
> +#define OPCODE_FAST_READ_4B	0x0c    /* Read data bytes (high frequency) */
> +#define OPCODE_PP_4B		0x12    /* Page program (up to 256 bytes) */
> +#define OPCODE_SE_4B		0xdc    /* Sector erase (usually 64KiB) */
> +
> +#ifdef CONFIG_SYS_FSL_QSPI_LE
> +#define qspi_read32		in_le32
> +#define qspi_write32		out_le32
> +#elif defined(CONFIG_SYS_FSL_QSPI_BE)
> +#define qspi_read32		in_be32
> +#define qspi_write32		out_be32
> +#endif
> +
> +static unsigned long spi_bases[] = {
> +	QSPI0_BASE_ADDR,
> +};
> +
> +static unsigned long amba_bases[] = {
> +	QSPI0_AMBA_BASE,
> +};
> +
> +struct fsl_qspi {
> +	struct spi_slave slave;
> +	unsigned long reg_base;
> +	unsigned long amba_base;
> +	u32 sf_addr;
> +	u8 cur_seqid;
> +};
> +
> +/* QSPI support swapping the flash read/write data
> + * in hardware for LS102xA, but not for VF610 */
> +static inline u32 qspi_endian_xchg(u32 data)
> +{
> +#ifdef CONFIG_VF610
> +	return swab32(data);
> +#else
> +	return data;
> +#endif
> +}
> +
> +static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave)
> +{
> +	return container_of(slave, struct fsl_qspi, slave);
> +}
> +
> +static void qspi_set_lut(struct fsl_qspi *qspi)
> +{
> +	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
> +	u32 lut_base;
> +
> +	/* Unlock the LUT */
> +	qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
> +	qspi_write32(&regs->lckcr, QSPI_LCKCR_UNLOCK);
> +
> +	/* Write Enable */
> +	lut_base = SEQID_WREN * 4;
> +	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_WREN) |
> +		PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
> +	qspi_write32(&regs->lut[lut_base + 1], 0);
> +	qspi_write32(&regs->lut[lut_base + 2], 0);
> +	qspi_write32(&regs->lut[lut_base + 3], 0);
> +
> +	/* Fast Read */
> +	lut_base = SEQID_FAST_READ * 4;
> +	if (FSL_QSPI_FLASH_SIZE  <= SZ_16M)
> +		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_FAST_READ) |
> +			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
> +			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
> +	else
> +		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_FAST_READ_4B) |
> +			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
> +			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
> +	qspi_write32(&regs->lut[lut_base + 1], OPRND0(8) | PAD0(LUT_PAD1) |
> +		INSTR0(LUT_DUMMY) | OPRND1(RX_BUFFER_SIZE) | PAD1(LUT_PAD1) |
> +		INSTR1(LUT_READ));
> +	qspi_write32(&regs->lut[lut_base + 2], 0);
> +	qspi_write32(&regs->lut[lut_base + 3], 0);
> +
> +	/* Read Status */
> +	lut_base = SEQID_RDSR * 4;
> +	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_RDSR) |
> +		PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
> +		PAD1(LUT_PAD1) | INSTR1(LUT_READ));
> +	qspi_write32(&regs->lut[lut_base + 1], 0);
> +	qspi_write32(&regs->lut[lut_base + 2], 0);
> +	qspi_write32(&regs->lut[lut_base + 3], 0);
> +
> +	/* Erase a sector */
> +	lut_base = SEQID_SE * 4;
> +	if (FSL_QSPI_FLASH_SIZE  <= SZ_16M)
> +		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_SE) |
> +			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
> +			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
> +	else
> +		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_SE_4B) |
> +			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
> +			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
> +	qspi_write32(&regs->lut[lut_base + 1], 0);
> +	qspi_write32(&regs->lut[lut_base + 2], 0);
> +	qspi_write32(&regs->lut[lut_base + 3], 0);
> +
> +	/* Erase the whole chip */
> +	lut_base = SEQID_CHIP_ERASE * 4;
> +	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_CHIP_ERASE) |
> +		PAD0(LUT_PAD1) | INSTR0(LUT_CMD));
> +	qspi_write32(&regs->lut[lut_base + 1], 0);
> +	qspi_write32(&regs->lut[lut_base + 2], 0);
> +	qspi_write32(&regs->lut[lut_base + 3], 0);
> +
> +	/* Page Program */
> +	lut_base = SEQID_PP * 4;
> +	if (FSL_QSPI_FLASH_SIZE  <= SZ_16M)
> +		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_PP) |
> +			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
> +			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
> +	else
> +		qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_PP_4B) |
> +			PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(ADDR32BIT) |
> +			PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
> +	qspi_write32(&regs->lut[lut_base + 1], OPRND0(TX_BUFFER_SIZE) |
> +		PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
> +	qspi_write32(&regs->lut[lut_base + 2], 0);
> +	qspi_write32(&regs->lut[lut_base + 3], 0);
> +
> +	/* READ ID */
> +	lut_base = SEQID_RDID * 4;
> +	qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_RDID) |
> +		PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(8) |
> +		PAD1(LUT_PAD1) | INSTR1(LUT_READ));
> +	qspi_write32(&regs->lut[lut_base + 1], 0);
> +	qspi_write32(&regs->lut[lut_base + 2], 0);
> +	qspi_write32(&regs->lut[lut_base + 3], 0);
> +
> +	/* Lock the LUT */
> +	qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
> +	qspi_write32(&regs->lckcr, QSPI_LCKCR_LOCK);
> +}
> +
> +void spi_init()
> +{
> +	/* do nothing */
> +}
> +
> +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> +		unsigned int max_hz, unsigned int mode)
> +{
> +	struct fsl_qspi *qspi;
> +	struct fsl_qspi_regs *regs;
> +	u32 reg_val, smpr_val;
> +	u32 total_size, seq_id;
> +
> +	if (bus >= ARRAY_SIZE(spi_bases))
> +		return NULL;
> +
> +	qspi = spi_alloc_slave(struct fsl_qspi, bus, cs);
> +	if (!qspi)
> +		return NULL;
> +
> +	qspi->reg_base = spi_bases[bus];
> +	qspi->amba_base = amba_bases[bus];
> +
> +	qspi->slave.max_write_size = TX_BUFFER_SIZE;
> +
> +	regs = (struct fsl_qspi_regs *)qspi->reg_base;
> +	qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
> +
> +	smpr_val = qspi_read32(&regs->smpr);
> +	qspi_write32(&regs->smpr, smpr_val & ~(QSPI_SMPR_FSDLY_MASK |
> +		QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK));
> +	qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
> +
> +	total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
> +	qspi_write32(&regs->sfa1ad, FSL_QSPI_FLASH_SIZE | qspi->amba_base);
> +	qspi_write32(&regs->sfa2ad, FSL_QSPI_FLASH_SIZE | qspi->amba_base);
> +	qspi_write32(&regs->sfb1ad, total_size | qspi->amba_base);
> +	qspi_write32(&regs->sfb2ad, total_size | qspi->amba_base);
> +
> +	qspi_set_lut(qspi);
> +
> +	smpr_val = qspi_read32(&regs->smpr);
> +	smpr_val &= ~QSPI_SMPR_DDRSMP_MASK;
> +	qspi_write32(&regs->smpr, smpr_val);
> +	qspi_write32(&regs->mcr, QSPI_MCR_RESERVED_MASK);
> +
> +	seq_id = 0;
> +	reg_val = qspi_read32(&regs->bfgencr);
> +	reg_val &= ~QSPI_BFGENCR_SEQID_MASK;
> +	reg_val |= (seq_id << QSPI_BFGENCR_SEQID_SHIFT);
> +	reg_val &= ~QSPI_BFGENCR_PAR_EN_MASK;
> +	qspi_write32(&regs->bfgencr, reg_val);
> +
> +	return &qspi->slave;
> +}
> +
> +void spi_free_slave(struct spi_slave *slave)
> +{
> +	struct fsl_qspi *qspi = to_qspi_spi(slave);
> +
> +	free(qspi);
> +}
> +
> +int spi_claim_bus(struct spi_slave *slave)
> +{
> +	return 0;
> +}
> +
> +static void qspi_op_rdid(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
> +{
> +	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
> +	u32 mcr_reg, rbsr_reg, data;
> +	int i, size;
> +
> +	mcr_reg = qspi_read32(&regs->mcr);
> +	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
> +		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
> +	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
> +
> +	qspi_write32(&regs->sfar, qspi->amba_base);
> +
> +	qspi_write32(&regs->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0);
> +	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +		;
> +
> +	i = 0;
> +	size = len;
> +	while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
> +		rbsr_reg = qspi_read32(&regs->rbsr);
> +		if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
> +			data = qspi_read32(&regs->rbdr[i]);
> +			data = qspi_endian_xchg(data);
> +			memcpy(rxbuf, &data, 4);
> +			rxbuf++;
> +			size -= 4;
> +			i++;
> +		}
> +	}
> +
> +	qspi_write32(&regs->mcr, mcr_reg);
> +}
> +
> +static void qspi_op_read(struct fsl_qspi *qspi, u32 *rxbuf, u32 len)
> +{
> +	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
> +	u32 mcr_reg, data;
> +	int i, size;
> +	u32 to_or_from;
> +
> +	mcr_reg = qspi_read32(&regs->mcr);
> +	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
> +		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
> +	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
> +
> +	to_or_from = qspi->sf_addr + qspi->amba_base;
> +
> +	while (len > 0) {
> +		qspi_write32(&regs->sfar, to_or_from);
> +
> +		size = (len > RX_BUFFER_SIZE) ?
> +			RX_BUFFER_SIZE : len;
> +
> +		qspi_write32(&regs->ipcr,
> +			(SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) | size);
> +		while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +			;
> +
> +		to_or_from += size;
> +		len -= size;
> +
> +		i = 0;
> +		while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
> +			data = qspi_read32(&regs->rbdr[i]);
> +			data = qspi_endian_xchg(data);
> +			memcpy(rxbuf, &data, 4);
> +			rxbuf++;
> +			size -= 4;
> +			i++;
> +		}
> +		qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
> +			QSPI_MCR_CLR_RXF_MASK);
> +	}
> +
> +	qspi_write32(&regs->mcr, mcr_reg);
> +}
> +
> +static void qspi_op_pp(struct fsl_qspi *qspi, u32 *txbuf, u32 len)
> +{
> +	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
> +	u32 mcr_reg, data, reg, status_reg;
> +	int i, size, tx_size;
> +	u32 to_or_from = 0;
> +
> +	mcr_reg = qspi_read32(&regs->mcr);
> +	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
> +		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
> +	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
> +
> +	status_reg = 0;
> +	while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) {
> +		qspi_write32(&regs->ipcr,
> +			(SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
> +		while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +			;
> +
> +		qspi_write32(&regs->ipcr,
> +			(SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
> +		while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +			;
> +
> +		reg = qspi_read32(&regs->rbsr);
> +		if (reg & QSPI_RBSR_RDBFL_MASK) {
> +			status_reg = qspi_read32(&regs->rbdr[0]);
> +			status_reg = qspi_endian_xchg(status_reg);
> +		}
> +		qspi_write32(&regs->mcr,
> +			qspi_read32(&regs->mcr) | QSPI_MCR_CLR_RXF_MASK);
> +	}
> +
> +	to_or_from = qspi->sf_addr + qspi->amba_base;
> +	qspi_write32(&regs->sfar, to_or_from);
> +
> +	tx_size = (len > TX_BUFFER_SIZE) ?
> +		TX_BUFFER_SIZE : len;
> +
> +	size = (tx_size + 3) / 4;
> +
> +	for (i = 0; i < size; i++) {
> +		data = qspi_endian_xchg(*txbuf);
> +		qspi_write32(&regs->tbdr, data);
> +		txbuf++;
> +	}
> +
> +	qspi_write32(&regs->ipcr,
> +		(SEQID_PP << QSPI_IPCR_SEQID_SHIFT) | tx_size);
> +	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +		;
> +
> +	qspi_write32(&regs->mcr, mcr_reg);
> +}
> +
> +static void qspi_op_rdsr(struct fsl_qspi *qspi, u32 *rxbuf)
> +{
> +	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
> +	u32 mcr_reg, reg, data;
> +
> +	mcr_reg = qspi_read32(&regs->mcr);
> +	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
> +		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
> +	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
> +
> +	qspi_write32(&regs->sfar, qspi->amba_base);
> +
> +	qspi_write32(&regs->ipcr,
> +		(SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0);
> +	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +		;
> +
> +	while (1) {
> +		reg = qspi_read32(&regs->rbsr);
> +		if (reg & QSPI_RBSR_RDBFL_MASK) {
> +			data = qspi_read32(&regs->rbdr[0]);
> +			data = qspi_endian_xchg(data);
> +			memcpy(rxbuf, &data, 4);
> +			qspi_write32(&regs->mcr, qspi_read32(&regs->mcr) |
> +				QSPI_MCR_CLR_RXF_MASK);
> +			break;
> +		}
> +	}
> +
> +	qspi_write32(&regs->mcr, mcr_reg);
> +}
> +
> +static void qspi_op_se(struct fsl_qspi *qspi)
> +{
> +	struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
> +	u32 mcr_reg;
> +	u32 to_or_from = 0;
> +
> +	mcr_reg = qspi_read32(&regs->mcr);
> +	qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
> +		QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
> +	qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
> +
> +	to_or_from = qspi->sf_addr + qspi->amba_base;
> +	qspi_write32(&regs->sfar, to_or_from);
> +
> +	qspi_write32(&regs->ipcr,
> +		(SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
> +	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +		;
> +
> +	qspi_write32(&regs->ipcr,
> +		(SEQID_SE << QSPI_IPCR_SEQID_SHIFT) | 0);
> +	while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
> +		;
> +
> +	qspi_write32(&regs->mcr, mcr_reg);
> +}
> +
> +int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> +		const void *dout, void *din, unsigned long flags)
> +{
> +	struct fsl_qspi *qspi = to_qspi_spi(slave);
> +	u32 bytes = DIV_ROUND_UP(bitlen, 8);
> +	static u32 pp_sfaddr;
> +	u32 txbuf;
> +
> +	if (dout) {
> +		memcpy(&txbuf, dout, 4);
> +		qspi->cur_seqid = *(u8 *)dout;
> +
> +		if (flags == SPI_XFER_END) {
> +			qspi->sf_addr = pp_sfaddr;
> +			qspi_op_pp(qspi, (u32 *)dout, bytes);
> +			return 0;
> +		}
> +
> +		if (qspi->cur_seqid == OPCODE_FAST_READ) {
> +			qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
> +		} else if (qspi->cur_seqid == OPCODE_SE) {
> +			qspi->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
> +			qspi_op_se(qspi);
> +		} else if (qspi->cur_seqid == OPCODE_PP) {
> +			pp_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
> +		}
> +	}
> +
> +	if (din) {
> +		if (qspi->cur_seqid == OPCODE_FAST_READ)
> +			qspi_op_read(qspi, din, bytes);
> +		else if (qspi->cur_seqid == OPCODE_RDID)
> +			qspi_op_rdid(qspi, din, bytes);
> +		else if (qspi->cur_seqid == OPCODE_RDSR)
> +			qspi_op_rdsr(qspi, din);
> +	}
> +
> +	return 0;
> +}
> +
> +void spi_release_bus(struct spi_slave *slave)
> +{
> +	/* Nothing to do */
> +}
> diff --git a/drivers/spi/fsl_qspi.h b/drivers/spi/fsl_qspi.h
> new file mode 100644
> index 0000000..db400e6
> --- /dev/null
> +++ b/drivers/spi/fsl_qspi.h
> @@ -0,0 +1,127 @@
> +/*
> + * Copyright 2013-2014 Freescale Semiconductor, Inc.
> + *
> + * Register definitions for Freescale QSPI
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef _FSL_QSPI_H_
> +#define _FSL_QSPI_H_
> +
> +struct fsl_qspi_regs {
> +	u32 mcr;
> +	u32 rsvd0[1];
> +	u32 ipcr;
> +	u32 flshcr;
> +	u32 buf0cr;
> +	u32 buf1cr;
> +	u32 buf2cr;
> +	u32 buf3cr;
> +	u32 bfgencr;
> +	u32 soccr;
> +	u32 rsvd1[2];
> +	u32 buf0ind;
> +	u32 buf1ind;
> +	u32 buf2ind;
> +	u32 rsvd2[49];
> +	u32 sfar;
> +	u32 rsvd3[1];
> +	u32 smpr;
> +	u32 rbsr;
> +	u32 rbct;
> +	u32 rsvd4[15];
> +	u32 tbsr;
> +	u32 tbdr;
> +	u32 rsvd5[1];
> +	u32 sr;
> +	u32 fr;
> +	u32 rser;
> +	u32 spndst;
> +	u32 sptrclr;
> +	u32 rsvd6[4];
> +	u32 sfa1ad;
> +	u32 sfa2ad;
> +	u32 sfb1ad;
> +	u32 sfb2ad;
> +	u32 rsvd7[28];
> +	u32 rbdr[32];
> +	u32 rsvd8[32];
> +	u32 lutkey;
> +	u32 lckcr;
> +	u32 rsvd9[2];
> +	u32 lut[64];
> +};
> +
> +#define QSPI_IPCR_SEQID_SHIFT		24
> +#define QSPI_IPCR_SEQID_MASK		(0xf << QSPI_IPCR_SEQID_SHIFT)
> +
> +#define QSPI_MCR_END_CFD_SHIFT		2
> +#define QSPI_MCR_END_CFD_MASK		(3 << QSPI_MCR_END_CFD_SHIFT)
> +#define QSPI_MCR_END_CFD_LE		(1 << QSPI_MCR_END_CFD_SHIFT)
> +#define QSPI_MCR_DDR_EN_SHIFT		7
> +#define QSPI_MCR_DDR_EN_MASK		(1 << QSPI_MCR_DDR_EN_SHIFT)
> +#define QSPI_MCR_CLR_RXF_SHIFT		10
> +#define QSPI_MCR_CLR_RXF_MASK		(1 << QSPI_MCR_CLR_RXF_SHIFT)
> +#define QSPI_MCR_CLR_TXF_SHIFT		11
> +#define QSPI_MCR_CLR_TXF_MASK		(1 << QSPI_MCR_CLR_TXF_SHIFT)
> +#define QSPI_MCR_MDIS_SHIFT		14
> +#define QSPI_MCR_MDIS_MASK		(1 << QSPI_MCR_MDIS_SHIFT)
> +#define QSPI_MCR_RESERVED_SHIFT		16
> +#define QSPI_MCR_RESERVED_MASK		(0xf << QSPI_MCR_RESERVED_SHIFT)
> +
> +#define QSPI_SMPR_HSENA_SHIFT		0
> +#define QSPI_SMPR_HSENA_MASK		(1 << QSPI_SMPR_HSENA_SHIFT)
> +#define QSPI_SMPR_FSPHS_SHIFT		5
> +#define QSPI_SMPR_FSPHS_MASK		(1 << QSPI_SMPR_FSPHS_SHIFT)
> +#define QSPI_SMPR_FSDLY_SHIFT		6
> +#define QSPI_SMPR_FSDLY_MASK		(1 << QSPI_SMPR_FSDLY_SHIFT)
> +#define QSPI_SMPR_DDRSMP_SHIFT		16
> +#define QSPI_SMPR_DDRSMP_MASK		(7 << QSPI_SMPR_DDRSMP_SHIFT)
> +
> +#define QSPI_BFGENCR_SEQID_SHIFT	12
> +#define QSPI_BFGENCR_SEQID_MASK		(0xf << QSPI_BFGENCR_SEQID_SHIFT)
> +#define QSPI_BFGENCR_PAR_EN_SHIFT	16
> +#define QSPI_BFGENCR_PAR_EN_MASK	(1 << QSPI_BFGENCR_PAR_EN_SHIFT)
> +
> +#define QSPI_RBSR_RDBFL_SHIFT		8
> +#define QSPI_RBSR_RDBFL_MASK		(0x3f << QSPI_RBSR_RDBFL_SHIFT)
> +
> +#define QSPI_RBCT_RXBRD_SHIFT		8
> +#define QSPI_RBCT_RXBRD_USEIPS		(1 << QSPI_RBCT_RXBRD_SHIFT)
> +
> +#define QSPI_SR_BUSY_SHIFT		0
> +#define QSPI_SR_BUSY_MASK		(1 << QSPI_SR_BUSY_SHIFT)
> +
> +#define QSPI_LCKCR_LOCK			0x1
> +#define QSPI_LCKCR_UNLOCK		0x2
> +
> +#define LUT_KEY_VALUE			0x5af05af0
> +
> +#define OPRND0_SHIFT			0
> +#define OPRND0(x)			((x) << OPRND0_SHIFT)
> +#define PAD0_SHIFT			8
> +#define PAD0(x)				((x) << PAD0_SHIFT)
> +#define INSTR0_SHIFT			10
> +#define INSTR0(x)			((x) << INSTR0_SHIFT)
> +#define OPRND1_SHIFT			16
> +#define OPRND1(x)			((x) << OPRND1_SHIFT)
> +#define PAD1_SHIFT			24
> +#define PAD1(x)				((x) << PAD1_SHIFT)
> +#define INSTR1_SHIFT			26
> +#define INSTR1(x)			((x) << INSTR1_SHIFT)
> +
> +#define LUT_CMD				1
> +#define LUT_ADDR			2
> +#define LUT_DUMMY			3
> +#define LUT_READ			7
> +#define LUT_WRITE			8
> +
> +#define LUT_PAD1			0
> +#define LUT_PAD2			1
> +#define LUT_PAD4			2
> +
> +#define ADDR24BIT			0x18
> +#define ADDR32BIT			0x20
> +
> +#endif /* _FSL_QSPI_H_ */

Whole series applied to u-boot-arm/master, thanks!

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-06-09  8:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-06  1:13 [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support Chao Fu
2014-05-06  1:13 ` [U-Boot] [PATCH 2/3] arm: imx: Add two macros for VF610 in IOMUX_PAD structure Chao Fu
2014-05-06  1:13 ` [U-Boot] [PATCH 3/3] arm: vf610: Add QSPI support for VF610TWR Chao Fu
2014-06-09  8:09 ` [U-Boot] [PATCH 1/3] arm: vf610: Add QSPI driver support Albert ARIBAUD

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.