blob: 8439dbdeb8b7f331747fc0a593b3f0c246465641 [file] [log] [blame]
/*
* Freescale QuadSPI driver.
*
* Copyright (C) 2014 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <common.h>
#include <malloc.h>
#include <spi.h>
#include <asm/io.h>
#define QUADSPI_AHBMAP_BANK_MAXSIZE SZ_64M
/* The registers */
#define QUADSPI_MCR 0x00
#define QUADSPI_MCR_RESERVED_SHIFT 16
#define QUADSPI_MCR_RESERVED_MASK (0xF << QUADSPI_MCR_RESERVED_SHIFT)
#define QUADSPI_MCR_MDIS_SHIFT 14
#define QUADSPI_MCR_MDIS_MASK (1 << QUADSPI_MCR_MDIS_SHIFT)
#define QUADSPI_MCR_CLR_TXF_SHIFT 11
#define QUADSPI_MCR_CLR_TXF_MASK (1 << QUADSPI_MCR_CLR_TXF_SHIFT)
#define QUADSPI_MCR_CLR_RXF_SHIFT 10
#define QUADSPI_MCR_CLR_RXF_MASK (1 << QUADSPI_MCR_CLR_RXF_SHIFT)
#define QUADSPI_MCR_DDR_EN_SHIFT 7
#define QUADSPI_MCR_DDR_EN_MASK (1 << QUADSPI_MCR_DDR_EN_SHIFT)
#define QUADSPI_MCR_END_CFG_SHIFT 2
#define QUADSPI_MCR_END_CFG_MASK (3 << QUADSPI_MCR_END_CFG_SHIFT)
#define QUADSPI_MCR_SWRSTHD_SHIFT 1
#define QUADSPI_MCR_SWRSTHD_MASK (1 << QUADSPI_MCR_SWRSTHD_SHIFT)
#define QUADSPI_MCR_SWRSTSD_SHIFT 0
#define QUADSPI_MCR_SWRSTSD_MASK (1 << QUADSPI_MCR_SWRSTSD_SHIFT)
#define QUADSPI_IPCR 0x08
#define QUADSPI_IPCR_SEQID_SHIFT 24
#define QUADSPI_IPCR_SEQID_MASK (0xF << QUADSPI_IPCR_SEQID_SHIFT)
#define QUADSPI_BUF0CR 0x10
#define QUADSPI_BUF1CR 0x14
#define QUADSPI_BUF2CR 0x18
#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe
#define QUADSPI_BUF3CR 0x1c
#define QUADSPI_BUF3CR_ALLMST_SHIFT 31
#define QUADSPI_BUF3CR_ALLMST_MASK (1 << QUADSPI_BUF3CR_ALLMST_SHIFT)
#define QUADSPI_BUF3CR_ADATSZ_SHIFT 8
#define QUADSPI_BUF3CR_ADATSZ_MASK (0xFF << QUADSPI_BUF3CR_ADATSZ_SHIFT)
#define QUADSPI_BFGENCR 0x20
#define QUADSPI_BFGENCR_PAR_EN_SHIFT 16
#define QUADSPI_BFGENCR_PAR_EN_MASK (1 << (QUADSPI_BFGENCR_PAR_EN_SHIFT))
#define QUADSPI_BFGENCR_SEQID_SHIFT 12
#define QUADSPI_BFGENCR_SEQID_MASK (0xF << QUADSPI_BFGENCR_SEQID_SHIFT)
#define QUADSPI_BUF0IND 0x30
#define QUADSPI_BUF1IND 0x34
#define QUADSPI_BUF2IND 0x38
#define QUADSPI_SFAR 0x100
#define QUADSPI_SMPR 0x108
#define QUADSPI_SMPR_DDRSMP_SHIFT 16
#define QUADSPI_SMPR_DDRSMP_MASK (7 << QUADSPI_SMPR_DDRSMP_SHIFT)
#define QUADSPI_SMPR_FSDLY_SHIFT 6
#define QUADSPI_SMPR_FSDLY_MASK (1 << QUADSPI_SMPR_FSDLY_SHIFT)
#define QUADSPI_SMPR_FSPHS_SHIFT 5
#define QUADSPI_SMPR_FSPHS_MASK (1 << QUADSPI_SMPR_FSPHS_SHIFT)
#define QUADSPI_SMPR_HSENA_SHIFT 0
#define QUADSPI_SMPR_HSENA_MASK (1 << QUADSPI_SMPR_HSENA_SHIFT)
#define QUADSPI_RBSR 0x10c
#define QUADSPI_RBSR_RDBFL_SHIFT 8
#define QUADSPI_RBSR_RDBFL_MASK (0x3F << QUADSPI_RBSR_RDBFL_SHIFT)
#define QUADSPI_RBCT 0x110
#define QUADSPI_RBCT_WMRK_MASK 0x1F
#define QUADSPI_RBCT_RXBRD_SHIFT 8
#define QUADSPI_RBCT_RXBRD_USEIPS (0x1 << QUADSPI_RBCT_RXBRD_SHIFT)
#define QUADSPI_TBSR 0x150
#define QUADSPI_TBDR 0x154
#define QUADSPI_SR 0x15c
#define QUADSPI_SR_IP_ACC_SHIFT 1
#define QUADSPI_SR_IP_ACC_MASK (0x1 << QUADSPI_SR_IP_ACC_SHIFT)
#define QUADSPI_SR_AHB_ACC_SHIFT 2
#define QUADSPI_SR_AHB_ACC_MASK (0x1 << QUADSPI_SR_AHB_ACC_SHIFT)
#define QUADSPI_FR 0x160
#define QUADSPI_FR_TFF_MASK 0x1
#define QUADSPI_SFA1AD 0x180
#define QUADSPI_SFA2AD 0x184
#define QUADSPI_SFB1AD 0x188
#define QUADSPI_SFB2AD 0x18c
#define QUADSPI_RBDR 0x200
#define QUADSPI_LUTKEY 0x300
#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0
#define QUADSPI_LCKCR 0x304
#define QUADSPI_LCKER_LOCK 0x1
#define QUADSPI_LCKER_UNLOCK 0x2
#define QUADSPI_RSER 0x164
#define QUADSPI_RSER_TFIE (0x1 << 0)
#define QUADSPI_LUT_BASE 0x310
/*
* The definition of the LUT register shows below:
*
* ---------------------------------------------------
* | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 |
* ---------------------------------------------------
*/
#define OPRND0_SHIFT 0
#define PAD0_SHIFT 8
#define INSTR0_SHIFT 10
#define OPRND1_SHIFT 16
/* Instruction set for the LUT register. */
#define LUT_STOP 0
#define LUT_CMD 1
#define LUT_ADDR 2
#define LUT_DUMMY 3
#define LUT_MODE 4
#define LUT_MODE2 5
#define LUT_MODE4 6
#define LUT_READ 7
#define LUT_WRITE 8
#define LUT_JMP_ON_CS 9
#define LUT_ADDR_DDR 10
#define LUT_MODE_DDR 11
#define LUT_MODE2_DDR 12
#define LUT_MODE4_DDR 13
#define LUT_READ_DDR 14
#define LUT_WRITE_DDR 15
#define LUT_DATA_LEARN 16
/*
* The PAD definitions for LUT register.
*
* The pad stands for the lines number of IO[0:3].
* For example, the Quad read need four IO lines, so you should
* set LUT_PAD4 which means we use four IO lines.
*/
#define LUT_PAD1 0
#define LUT_PAD2 1
#define LUT_PAD4 2
/* Oprands for the LUT register. */
#define ADDR24BIT 0x18
#define ADDR32BIT 0x20
/* Macros for constructing the LUT register. */
#define LUT0(ins, pad, opr) \
(((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \
((LUT_##ins) << INSTR0_SHIFT))
#define LUT1(ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT)
/* other macros for LUT register. */
#define QUADSPI_LUT(x) (QUADSPI_LUT_BASE + (x) * 4)
#define QUADSPI_LUT_NUM 64
/* SEQID -- we can have 16 seqids at most. */
#define SEQID_QUAD_READ 0
#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
#define SEQID_WRSR 8
#define SEQID_RDCR 9
#define SEQID_DDR_QUAD_READ 10
#define SEQID_BE_4K 11
#ifdef CONFIG_SPI_FLASH_BAR
#define SEQID_BRRD 12
#define SEQID_BRWR 13
#define SEQID_RDEAR 14
#define SEQID_WREAR 15
#endif
/* Flash opcodes. */
#define OPCODE_WREN 0x06 /* Write enable */
#define OPCODE_RDSR 0x05 /* Read status register */
#define OPCODE_WRSR 0x01 /* Write status register 1 byte */
#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */
#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
#define OPCODE_QUAD_READ 0x6b /* Read data bytes */
#define OPCODE_DDR_QUAD_READ 0x6d /* Read data bytes in DDR mode*/
#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
#define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */
#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
#define OPCODE_RDID 0x9f /* Read JEDEC ID */
#define OPCODE_RDCR 0x35 /* Read configuration register */
/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
#define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */
#define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */
#define OPCODE_QUAD_READ_4B 0x6c /* Read data bytes */
#define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */
#define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */
/* Used for SST flashes only. */
#define OPCODE_BP 0x02 /* Byte program */
#define OPCODE_WRDI 0x04 /* Write disable */
#define OPCODE_AAI_WP 0xad /* Auto address increment word program */
/* Used for Macronix and Winbond flashes. */
#define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */
#define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */
/* Used for Micron, winbond and Macronix flashes */
#define OPCODE_WREAR 0xc5 /* EAR register write */
#define OPCODE_RDEAR 0xc8 /* EAR reigster read */
/* Used for Spansion flashes only. */
#define OPCODE_BRRD 0x16 /* Bank register read */
#define OPCODE_BRWR 0x17 /* Bank register write */
/* Status Register bits. */
#define SR_WIP 1 /* Write in progress */
#define SR_WEL 2 /* Write enable latch */
/* meaning of other SR_* bits may differ between vendors */
#define SR_BP0 4 /* Block protect 0 */
#define SR_BP1 8 /* Block protect 1 */
#define SR_BP2 0x10 /* Block protect 2 */
#define SR_SRWD 0x80 /* SR write protect */
#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */
/* Configuration Register bits. */
#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */
/* Endianess Configuration */
#define BE_64 0x00
#define LE_32 0x01
#define BE_32 0x02
#define LE_64 0x03
enum fsl_qspi_devtype {
FSL_QUADSPI_VYBRID,
FSL_QUADSPI_IMX6SX,
};
struct fsl_qspi_devtype_data {
enum fsl_qspi_devtype devtype;
int rxfifo;
int txfifo;
};
struct fsl_qspi {
struct spi_slave slave;
uint32_t max_khz;
uint32_t mode;
u32 iobase;
u32 ahb_base; /* Used when read from AHB bus */
u32 bank_memmap_phy[4];
struct fsl_qspi_devtype_data *devtype_data;
};
static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q)
{
writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
writel(QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
}
static inline void fsl_qspi_lock_lut(struct fsl_qspi *q)
{
writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
writel(QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
}
static void fsl_qspi_init_lut(struct fsl_qspi *q)
{
u32 base = q->iobase;
int rxfifo = q->devtype_data->rxfifo;
u32 lut_base;
u8 cmd, addrlen, dummy;
int i;
fsl_qspi_unlock_lut(q);
/* Clear all the LUT table */
for (i = 0; i < QUADSPI_LUT_NUM; i++)
writel(0, base + QUADSPI_LUT_BASE + i * 4);
/* Quad Read */
lut_base = SEQID_QUAD_READ * 4;
/* U-boot SPI flash only support 24bits address*/
cmd = OPCODE_QUAD_READ;
addrlen = ADDR24BIT;
dummy = 8;
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ, PAD4, rxfifo),
base + QUADSPI_LUT(lut_base + 1));
/* Write enable */
lut_base = SEQID_WREN * 4;
writel(LUT0(CMD, PAD1, OPCODE_WREN), base + QUADSPI_LUT(lut_base));
/* Fast Read */
lut_base = SEQID_FAST_READ * 4;
cmd = OPCODE_FAST_READ;
addrlen = ADDR24BIT;
dummy = 8;
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ, PAD1, rxfifo),
base + QUADSPI_LUT(lut_base + 1));
/* Page Program */
lut_base = SEQID_PP * 4;
cmd = OPCODE_PP;
addrlen = ADDR24BIT;
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
writel(LUT0(WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1));
/* Read Status */
lut_base = SEQID_RDSR * 4;
writel(LUT0(CMD, PAD1, OPCODE_RDSR) | LUT1(READ, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
/* Erase a sector */
lut_base = SEQID_SE * 4;
cmd = OPCODE_SE;
addrlen = ADDR24BIT;
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
/* Erase the whole chip */
lut_base = SEQID_CHIP_ERASE * 4;
writel(LUT0(CMD, PAD1, OPCODE_CHIP_ERASE),
base + QUADSPI_LUT(lut_base));
/* READ ID */
lut_base = SEQID_RDID * 4;
writel(LUT0(CMD, PAD1, OPCODE_RDID) | LUT1(READ, PAD1, 0x8),
base + QUADSPI_LUT(lut_base));
/* Write Register */
lut_base = SEQID_WRSR * 4;
writel(LUT0(CMD, PAD1, OPCODE_WRSR) | LUT1(WRITE, PAD1, 0x2),
base + QUADSPI_LUT(lut_base));
/* Read Configuration Register */
lut_base = SEQID_RDCR * 4;
writel(LUT0(CMD, PAD1, OPCODE_RDCR) | LUT1(READ, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
/* DDR QUAD Read */
lut_base = SEQID_DDR_QUAD_READ * 4;
cmd = OPCODE_DDR_QUAD_READ;
addrlen = ADDR24BIT;
dummy = 6;
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR_DDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ_DDR, PAD4, rxfifo),
base + QUADSPI_LUT(lut_base + 1));
writel(LUT0(JMP_ON_CS, PAD1, 0),
base + QUADSPI_LUT(lut_base + 2));
/* SUB SECTOR 4K ERASE */
lut_base = SEQID_BE_4K * 4;
cmd = OPCODE_BE_4K;
addrlen = ADDR24BIT;
writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
base + QUADSPI_LUT(lut_base));
#ifdef CONFIG_SPI_FLASH_BAR
/*
* BRRD BRWR RDEAR WREAR are all supported, because it is hard to
* dynamically check whether to set BRRD BRWR or RDEAR WREAR.
*/
lut_base = SEQID_BRRD * 4;
cmd = OPCODE_BRRD;
writel(LUT0(CMD, PAD1, cmd) | LUT1(READ, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
lut_base = SEQID_BRWR * 4;
cmd = OPCODE_BRWR;
writel(LUT0(CMD, PAD1, cmd) | LUT1(WRITE, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
lut_base = SEQID_RDEAR * 4;
cmd = OPCODE_RDEAR;
writel(LUT0(CMD, PAD1, cmd) | LUT1(READ, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
lut_base = SEQID_WREAR * 4;
cmd = OPCODE_WREAR;
writel(LUT0(CMD, PAD1, cmd) | LUT1(WRITE, PAD1, 0x1),
base + QUADSPI_LUT(lut_base));
#endif
fsl_qspi_lock_lut(q);
}
/*Enable DDR Read Mode*/
static void fsl_enable_ddr_mode(struct fsl_qspi *q)
{
u32 base = q->iobase;
u32 reg, reg2;
reg = readl(base + QUADSPI_MCR);
/* Firstly, disable the module */
writel(reg | QUADSPI_MCR_MDIS_MASK, base + QUADSPI_MCR);
/* Set the Sampling Register for DDR */
reg2 = readl(base + QUADSPI_SMPR);
reg2 &= ~QUADSPI_SMPR_DDRSMP_MASK;
reg2 |= (2 << QUADSPI_SMPR_DDRSMP_SHIFT);
writel(reg2, base + QUADSPI_SMPR);
/* Enable the module again (enable the DDR too) */
reg |= QUADSPI_MCR_DDR_EN_MASK;
reg |= (1 << 29); /* enable bit 29 for imx6sx */
writel(reg, base + QUADSPI_MCR);
}
/*
* There are two different ways to read out the data from the flash:
* the "IP Command Read" and the "AHB Command Read".
*
* The IC guy suggests we use the "AHB Command Read" which is faster
* then the "IP Command Read". (What's more is that there is a bug in
* the "IP Command Read" in the Vybrid.)
*
* After we set up the registers for the "AHB Command Read", we can use
* the memcpy to read the data directly. A "missed" access to the buffer
* causes the controller to clear the buffer, and use the sequence pointed
* by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash.
*/
static void fsl_qspi_init_abh_read(struct fsl_qspi *q)
{
u32 base = q->iobase;
/* Map the SPI NOR to accessiable address, arrage max space for each bank*/
writel(q->bank_memmap_phy[0] + QUADSPI_AHBMAP_BANK_MAXSIZE,
base + QUADSPI_SFA1AD);
writel(q->bank_memmap_phy[1] + QUADSPI_AHBMAP_BANK_MAXSIZE,
base + QUADSPI_SFA2AD);
writel(q->bank_memmap_phy[2] + QUADSPI_AHBMAP_BANK_MAXSIZE,
base + QUADSPI_SFB1AD);
writel(q->bank_memmap_phy[3] + QUADSPI_AHBMAP_BANK_MAXSIZE,
base + QUADSPI_SFB2AD);
/* AHB configuration for access buffer 0/1/2 .*/
writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR);
writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR);
writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR);
writel(QUADSPI_BUF3CR_ALLMST_MASK | (0x80 << QUADSPI_BUF3CR_ADATSZ_SHIFT),
base + QUADSPI_BUF3CR);
/* We only use the buffer3 */
writel(0, base + QUADSPI_BUF0IND);
writel(0, base + QUADSPI_BUF1IND);
writel(0, base + QUADSPI_BUF2IND);
/* Set the default lut sequence for AHB Read. */
writel(SEQID_FAST_READ << QUADSPI_BFGENCR_SEQID_SHIFT,
base + QUADSPI_BFGENCR);
/*Enable DDR Mode*/
fsl_enable_ddr_mode(q);
}
static int fsl_qspi_init(struct fsl_qspi *q)
{
u32 base = q->iobase;
u32 reg;
void *ptr;
ptr = malloc(sizeof(struct fsl_qspi_devtype_data));
if (!ptr) {
puts("FSL_QSPI: per-type data not allocated !\n");
return 1;
}
q->devtype_data = ptr;
q->devtype_data->rxfifo = 128;
q->devtype_data->txfifo = 512;
/* init the LUT table */
fsl_qspi_init_lut(q);
/* Disable the module */
writel(QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
base + QUADSPI_MCR);
reg = readl(base + QUADSPI_SMPR);
writel(reg & ~(QUADSPI_SMPR_FSDLY_MASK
| QUADSPI_SMPR_FSPHS_MASK
| QUADSPI_SMPR_HSENA_MASK
| QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR);
/* Enable the module */
writel(QUADSPI_MCR_RESERVED_MASK | LE_64 << QUADSPI_MCR_END_CFG_SHIFT,
base + QUADSPI_MCR);
/* We do not enable the interrupt */
/* init for AHB read */
fsl_qspi_init_abh_read(q);
/*
* High level code use page_size and max_write_size to calculate
* the number of bytes that should be programmed once.
*/
q->slave.max_write_size = q->devtype_data->txfifo;
return 0;
}
void spi_init(void)
{
}
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int mode)
{
struct fsl_qspi *q;
int ret;
if (bus > 1) {
puts("FSL_QSPI: Not a valid bus !\n");
return NULL;
}
if (cs > 1) {
puts("FSL_QSPI: Not a valid cs !\n");
return NULL;
}
q = spi_alloc_slave(struct fsl_qspi, bus, cs);
if (!q) {
puts("FSL_QSPI: SPI Slave not allocated !\n");
return NULL;
}
q->iobase = CONFIG_QSPI_BASE;
q->bank_memmap_phy[0] = CONFIG_QSPI_MEMMAP_BASE;
q->bank_memmap_phy[1] = q->bank_memmap_phy[0] + QUADSPI_AHBMAP_BANK_MAXSIZE;
q->bank_memmap_phy[2] = q->bank_memmap_phy[1] + QUADSPI_AHBMAP_BANK_MAXSIZE;
q->bank_memmap_phy[3] = q->bank_memmap_phy[2] + QUADSPI_AHBMAP_BANK_MAXSIZE;
/* Init the QuadSPI controller */
ret = fsl_qspi_init(q);
if (ret) {
puts("FSL_QSPI: init failed!\n");
return NULL;
}
return &q->slave;
}
void spi_free_slave(struct spi_slave *slave)
{
struct fsl_qspi *q;
q = container_of(slave, struct fsl_qspi, slave);
free(q->devtype_data);
free(q);
}
int spi_claim_bus(struct spi_slave *q)
{
return 0;
}
void spi_release_bus(struct spi_slave *q)
{
}
/* Get the SEQID for the command */
static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
{
switch (cmd) {
case OPCODE_QUAD_READ:
case OPCODE_QUAD_READ_4B:
return SEQID_QUAD_READ;
case OPCODE_FAST_READ:
case OPCODE_FAST_READ_4B:
return SEQID_FAST_READ;
case OPCODE_WREN:
return SEQID_WREN;
case OPCODE_RDSR:
return SEQID_RDSR;
case OPCODE_SE:
return SEQID_SE;
case OPCODE_CHIP_ERASE:
return SEQID_CHIP_ERASE;
case OPCODE_PP:
case OPCODE_PP_4B:
return SEQID_PP;
case OPCODE_RDID:
return SEQID_RDID;
case OPCODE_WRSR:
return SEQID_WRSR;
case OPCODE_RDCR:
return SEQID_RDCR;
case OPCODE_DDR_QUAD_READ:
return SEQID_DDR_QUAD_READ;
case OPCODE_BE_4K:
return SEQID_BE_4K;
#ifdef CONFIG_SPI_FLASH_BAR
case OPCODE_BRRD:
return SEQID_BRRD;
case OPCODE_BRWR:
return SEQID_BRWR;
case OPCODE_RDEAR:
return SEQID_RDEAR;
case OPCODE_WREAR:
return SEQID_WREAR;
#endif
default:
break;
}
return -1;
}
/* return 1 on success */
static int fsl_qspi_wait_to_complete(struct fsl_qspi *q)
{
u32 base = q->iobase;
u32 reg;
/*printf("QuadSPI: poll the busy bit\n");*/
while (1) {
reg = readl(base + QUADSPI_SR);
if (reg & 1)
continue;
else
return 1;
}
return 0;
}
/*
* If we have changed the content of the flash by writing or erasing,
* we need to invalidate the AHB buffer. If we do not do so, we may read out
* the wrong data. The spec tells us reset the AHB domain and Serial Flash
* domain at the same time.
*/
static inline void fsl_qspi_invalid(struct fsl_qspi *q)
{
u32 reg;
reg = readl(q->iobase + QUADSPI_MCR);
reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK;
writel(reg, q->iobase + QUADSPI_MCR);
/*
* The minimum delay : 1 AHB + 2 SFCK clocks.
* Delay 1 us is enough.
*/
udelay(1);
reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK);
writel(reg, q->iobase + QUADSPI_MCR);
}
static int
fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len)
{
u32 base = q->iobase;
int seqid;
u32 reg, reg2;
int err;
int bank_id;
/* check the SR first, wait previous cmd completed*/
do {
reg2 = readl(base + QUADSPI_SR);
if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) {
udelay(1);
printf("The controller is busy, 0x%x\n", reg2);
continue;
}
break;
} while (1);
/* save the reg */
reg = readl(base + QUADSPI_MCR);
/* get the bank index */
bank_id = ((q->slave.bus) << 1) + (q->slave.cs);
writel(q->bank_memmap_phy[bank_id] + addr, base + QUADSPI_SFAR);
writel(QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS,
base + QUADSPI_RBCT);
writel(reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR);
/* trigger the LUT now */
seqid = fsl_qspi_get_seqid(q, cmd);
writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR);
/* Wait until completed */
err = fsl_qspi_wait_to_complete(q);
if (!err)
err = -1;
else
err = 0;
/* restore the MCR */
writel(reg, base + QUADSPI_MCR);
/* After switch BANK, AHB buffer should also be invalid. */
if ((OPCODE_SE == cmd) || (OPCODE_PP == cmd) ||
(OPCODE_BE_4K == cmd) || (OPCODE_WREAR == cmd) ||
(OPCODE_BRWR == cmd))
fsl_qspi_invalid(q);
return err;
}
/*
* An IC bug makes us to re-arrange the 32-bit data.
* The following chips, such as IMX6SLX, have fixed this bug.
*/
static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a)
{
return a;
}
/* Read out the data from the AHB buffer. */
static void fsl_qspi_ahb_read(struct fsl_qspi *q,
unsigned int addr, int len, u8 *rxbuf)
{
int bank_id;
/* get the bank index */
bank_id = ((q->slave.bus) << 1) + (q->slave.cs);
/* Read out the data directly from the AHB buffer.*/
memcpy(rxbuf, (u8 *)(q->bank_memmap_phy[bank_id] + addr), len);
}
/* Read out the data from the QUADSPI_RBDR buffer registers. */
static void fsl_qspi_ip_read(struct fsl_qspi *q, int len, u8 *rxbuf)
{
u32 tmp;
int i = 0;
while (len > 0) {
tmp = readl(q->iobase + QUADSPI_RBDR + i * 4);
tmp = fsl_qspi_endian_xchg(q, tmp);
if (len >= 4) {
memcpy(rxbuf, &tmp, 4);
rxbuf += 4;
} else {
memcpy(rxbuf, &tmp, len);
break;
}
len -= 4;
i++;
}
}
/* Write data to the QUADSPI_TBDR buffer registers. */
static void fsl_qspi_write_data(struct fsl_qspi *q, int len, u8* txbuf)
{
u32 tmp;
u32 t1, t2;
int j;
/* clear the TX FIFO. */
tmp = readl(q->iobase + QUADSPI_MCR);
writel(tmp | QUADSPI_MCR_CLR_RXF_MASK, q->iobase + QUADSPI_MCR);
/* fill the TX data to the FIFO */
t2 = len % 4;
t1 = len >> 2; /* 4 Bytes aligned */
for (j = 0; j < t1; j++) {
memcpy(&tmp, txbuf, 4);
tmp = fsl_qspi_endian_xchg(q, tmp);
writel(tmp, q->iobase + QUADSPI_TBDR);
txbuf += 4;
}
if (t2) {
tmp = 0;
memcpy(&tmp, txbuf, t2);
tmp = fsl_qspi_endian_xchg(q, tmp);
writel(tmp, q->iobase + QUADSPI_TBDR);
}
}
/* see the spi_flash_read_write() */
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
void *din, unsigned long flags)
{
struct fsl_qspi *q = container_of(slave, struct fsl_qspi, slave);
int len = bitlen / 8;
int ret = 0;
u8 *buf;
static u8 opcode;
static unsigned int addr;
if (!opcode && (flags & SPI_XFER_BEGIN)) {
/* spi_xfer for cmd phase */
buf = (u8 *)dout;
opcode = buf[0];
if (len > 1)
addr = buf[1] << 16 | buf[2] << 8 | buf[3];
/* if transfer cmd only */
if (flags & SPI_XFER_END)
ret = fsl_qspi_runcmd(q, opcode, addr, 0);
} else if (opcode) {
/* spi_xfer for data phase */
if (din) {
/* read*/
buf = (u8 *)din;
if (OPCODE_FAST_READ == opcode) {
fsl_qspi_ahb_read(q, addr, len, buf);
} else {
ret = fsl_qspi_runcmd(q, opcode, addr, len);
if (!ret)
fsl_qspi_ip_read(q, len, buf);
}
} else if (dout) {
/* write data, prepare data first */
buf = (u8 *)dout;
fsl_qspi_write_data(q, len, buf);
/* then run page program cmd */
ret = fsl_qspi_runcmd(q, opcode, addr, len);
}
}
if (ret || (flags & SPI_XFER_END)) {
opcode = 0;
addr = 0;
}
return ret;
}