]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
Xilinx: ARM: spi: zynq: Add QUAD enable bit support for spansion flash
authorJagannadha Sutradharudu Teki <jaganna@xilinx.com>
Tue, 11 Sep 2012 06:45:39 +0000 (12:15 +0530)
committerJohn Linn <john.linn@xilinx.com>
Thu, 13 Sep 2012 00:43:20 +0000 (17:43 -0700)
This patch adds support to enable QUAD bit on spansion SPI flash.

QUAD bit needs to set for booting dual qspi on spansion flash.
The implementation will enable the quad bit only when not set.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
drivers/spi/zynq_qspi.c
drivers/spi/zynq_qspi.h
drivers/spi/zynq_qspi_wrap.c

index dd9d04fc4862e6ee9297d25cac32635fa9b01a5c..a9e5d03ee5566bc8aac0ab39327ecd130805d537 100755 (executable)
@@ -1421,3 +1421,37 @@ int xqspips_check_is_dual_flash(void __iomem *regs_base)
 
        return is_dual;
 }
+
+/**
+ * xqspips_write_quad_bit - Write 1 to QUAD bit on flash
+ *
+ * This function will write a 1 to quad bit in flash
+ * using QSPI controller and supports only spansion flash.
+ *
+ * @regs_base:  base address of QSPI controller
+ */
+void xqspips_write_quad_bit(void __iomem *regs_base)
+{
+       u32 config_reg, intr_status;
+
+       /* enable the QSPI controller */
+       xqspips_write(regs_base + XQSPIPSS_ENABLE_OFFSET,
+                       XQSPIPSS_ENABLE_ENABLE_MASK);
+
+       /* Write QUAD bit with 3-byte instruction */
+       xqspips_write(regs_base + XQSPIPSS_TXD_00_11_OFFSET, 0x20001);
+
+       /* Enable manual start command */
+       config_reg = xqspips_read(regs_base +
+               XQSPIPSS_CONFIG_OFFSET) | XQSPIPSS_CONFIG_MANSRT_MASK;
+       xqspips_write(regs_base + XQSPIPSS_CONFIG_OFFSET, config_reg);
+
+       /* Wait for the transfer to finish by polling Tx fifo status */
+       do {
+               intr_status = xqspips_read(regs_base +
+                       XQSPIPSS_STATUS_OFFSET);
+       } while ((intr_status & 0x04) == 0);
+
+       /* Read data receive register */
+       config_reg = xqspips_read(regs_base + XQSPIPSS_RXD_OFFSET);
+}
index c33cb138a00c2a0b6c230af9333c0548089e0c24..0a3ffe0b70d2e7ad19643d97937f5e7292c36907 100644 (file)
@@ -52,7 +52,13 @@ extern int  xqspips_setup_transfer(struct spi_device   *qspi,
 extern int  xqspips_transfer(struct spi_device   *qspi,
                               struct spi_transfer *transfer);
 extern int xqspips_check_is_dual_flash(void *regs_base);
+extern void xqspips_write_quad_bit(void *regs_base);
 
+/* Few mtd flash functions */
+extern int spi_flash_cmd(struct spi_slave *spi, u8 cmd,
+               void *response, size_t len);
+extern int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
+               size_t cmd_len, void *data, size_t data_len);
 /**************************************************************************/
 
 #endif
index 02234a411f159096fc78d9f54ed0899a06a5bb75..7516f3df8bf3de72a8c69ba93ca1162918ab66f1 100644 (file)
@@ -44,6 +44,79 @@ void spi_init()
        debug("spi_init\n");
 }
 
+/**
+ * spi_enable_quad_bit - Enable the QUAD bit for SPI flash
+ *
+ * This function will enable the quad bit in flash using
+ * the QSPI controller. Supports only spansion.
+ *
+ * @spi : SPI slave structure
+ */
+void spi_enable_quad_bit(struct spi_slave *spi)
+{
+       int ret;
+       u8 idcode[5];
+       u8 rdid_cmd = 0x9f;     /* RDID */
+       u8 rcr_data = 0;
+       u8 rcr_cmd = 0x35;      /* RCR */
+       u8 rdsr_cmd = 0x05;     /* RDSR */
+       u8 wren_cmd = 0x06;     /* WREN */
+
+       ret = spi_flash_cmd(spi, rdid_cmd, &idcode, sizeof(idcode));
+       if (ret) {
+               debug("SF error: Failed read RDID\n");
+               return;
+       }
+
+       if (idcode[0] == 0x01) {
+               /* Read config register */
+               ret = spi_flash_cmd_read(spi, &rcr_cmd, sizeof(rcr_cmd),
+                                       &rcr_data, sizeof(rcr_data));
+               if (ret) {
+                       debug("SF error: Failed read RCR\n");
+                       return;
+               }
+
+               if (rcr_data & 0x2)
+                       debug("QUAD bit is already set..\n");
+               else {
+                       debug("QUAD bit needs to be set ..\n");
+
+                       /* Write enable */
+                       ret = spi_flash_cmd(spi, wren_cmd, NULL, 0);
+                       if (ret) {
+                               debug("SF error: Failed write WREN\n");
+                               return;
+                       }
+
+                       /* Write QUAD bit */
+                       xqspips_write_quad_bit((void *)XPSS_QSPI_BASEADDR);
+
+                       /* Read RDSR */
+                       do {
+                               ret = spi_flash_cmd_read(spi, &rdsr_cmd,
+                                               sizeof(rdsr_cmd), &rcr_data,
+                                               sizeof(rcr_data));
+                       } while ((ret == 0) && (rcr_data != 0));
+
+                       /* Read config register */
+                       ret = spi_flash_cmd_read(spi, &rcr_cmd, sizeof(rcr_cmd),
+                                               &rcr_data, sizeof(rcr_data));
+                       if (!(rcr_data & 0x2)) {
+                               printf("SF error: Fail to set QUAD enable bit"
+                                       " 0x%x\n", rcr_data);
+                               return;
+                       } else
+                               debug("SF: QUAD enable bit is set 0x%x\n",
+                                               rcr_data);
+               }
+       } else
+               debug("SF: QUAD bit not enabled for 0x%x SPI flash\n",
+                                       idcode[0]);
+
+       return;
+}
+
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                unsigned int max_hz, unsigned int mode)
 {
@@ -81,6 +154,8 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
        pspi->qspi.bits_per_word = 32;
        xqspips_setup_transfer(&pspi->qspi, NULL);
 
+       spi_enable_quad_bit(&pspi->slave);
+
        return &pspi->slave;
 }