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(®s->mcr); qspi_write32(®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); qspi_write32(®s->rbct, QSPI_RBCT_RXBRD_USEIPS); status_reg = 0; while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) { qspi_write32(®s->ipcr, (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0); while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) ; qspi_write32(®s->ipcr, (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1); while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) ; reg = qspi_read32(®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { status_reg = qspi_read32(®s->rbdr[0]); status_reg = qspi_endian_xchg(status_reg); } qspi_write32(®s->mcr, qspi_read32(®s->mcr) | QSPI_MCR_CLR_RXF_MASK); } to_or_from = qspi->sf_addr + qspi->amba_base; qspi_write32(®s->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(®s->tbdr, data); txbuf++; } qspi_write32(®s->ipcr, (SEQID_PP << QSPI_IPCR_SEQID_SHIFT) | tx_size); while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) ; qspi_write32(®s->mcr, mcr_reg); }
static void qspi_op_rdsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len) { struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, reg, data; mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base); qspi_write32(priv->flags, ®s->ipcr, (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 0); while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ; while (1) { reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(priv->flags, ®s->rbdr[0]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, len); qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | QSPI_MCR_CLR_RXF_MASK); break; } } qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) { struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, rbsr_reg, data, size; int i; mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base); qspi_write32(priv->flags, ®s->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0); while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ; i = 0; while ((RX_BUFFER_SIZE >= len) && (len > 0)) { rbsr_reg = qspi_read32(priv->flags, ®s->rbsr); if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(priv->flags, ®s->rbdr[i]); data = qspi_endian_xchg(data); size = (len < 4) ? len : 4; memcpy(rxbuf, &data, size); len -= size; rxbuf++; i++; } } qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
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(®s->mcr); qspi_write32(®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); qspi_write32(®s->rbct, QSPI_RBCT_RXBRD_USEIPS); qspi_write32(®s->sfar, qspi->amba_base); qspi_write32(®s->ipcr, (SEQID_RDID << QSPI_IPCR_SEQID_SHIFT) | 0); while (qspi_read32(®s->sr) & QSPI_SR_BUSY_MASK) ; i = 0; size = len; while ((RX_BUFFER_SIZE >= size) && (size > 0)) { rbsr_reg = qspi_read32(®s->rbsr); if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(®s->rbdr[i]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, 4); rxbuf++; size -= 4; i++; } } qspi_write32(®s->mcr, mcr_reg); }
/* If not use AHB read, read data from ip interface */ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) { struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, data; int i, size; u32 to_or_from; mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); to_or_from = priv->sf_addr + priv->cur_amba_base; while (len > 0) { WATCHDOG_RESET(); qspi_write32(priv->flags, ®s->sfar, to_or_from); size = (len > RX_BUFFER_SIZE) ? RX_BUFFER_SIZE : len; qspi_write32(priv->flags, ®s->ipcr, (SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) | size); while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ; to_or_from += size; len -= size; i = 0; while ((RX_BUFFER_SIZE >= size) && (size > 0)) { data = qspi_read32(priv->flags, ®s->rbdr[i]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, 4); rxbuf++; size -= 4; i++; } qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | QSPI_MCR_CLR_RXF_MASK); } qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
/* Bank register read/write, EAR register read/write */ static void qspi_op_rdbank(struct fsl_qspi_priv *priv, u8 *rxbuf, u32 len) { struct fsl_qspi_regs *regs = priv->regs; u32 reg, mcr_reg, data, seqid; mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base); if (priv->cur_seqid == QSPI_CMD_BRRD) seqid = SEQID_BRRD; else seqid = SEQID_RDEAR; qspi_write32(priv->flags, ®s->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | len); /* Wait previous command complete */ while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ; while (1) { reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { data = qspi_read32(priv->flags, ®s->rbdr[0]); data = qspi_endian_xchg(data); memcpy(rxbuf, &data, len); qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | QSPI_MCR_CLR_RXF_MASK); break; } } qspi_write32(priv->flags, ®s->mcr, mcr_reg); }
static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) { struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg, data, reg, status_reg, seqid; int i, size, tx_size; u32 to_or_from = 0; mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); status_reg = 0; while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) { WATCHDOG_RESET(); qspi_write32(priv->flags, ®s->ipcr, (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0); while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ; qspi_write32(priv->flags, ®s->ipcr, (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1); while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ; reg = qspi_read32(priv->flags, ®s->rbsr); if (reg & QSPI_RBSR_RDBFL_MASK) { status_reg = qspi_read32(priv->flags, ®s->rbdr[0]); status_reg = qspi_endian_xchg(status_reg); } qspi_write32(priv->flags, ®s->mcr, qspi_read32(priv->flags, ®s->mcr) | QSPI_MCR_CLR_RXF_MASK); } /* Default is page programming */ seqid = SEQID_PP; #ifdef CONFIG_SPI_FLASH_BAR if (priv->cur_seqid == QSPI_CMD_BRWR) seqid = SEQID_BRWR; else if (priv->cur_seqid == QSPI_CMD_WREAR) seqid = SEQID_WREAR; #endif to_or_from = priv->sf_addr + priv->cur_amba_base; qspi_write32(priv->flags, ®s->sfar, to_or_from); tx_size = (len > TX_BUFFER_SIZE) ? TX_BUFFER_SIZE : len; size = tx_size / 4; for (i = 0; i < size; i++) { memcpy(&data, txbuf, 4); data = qspi_endian_xchg(data); qspi_write32(priv->flags, ®s->tbdr, data); txbuf += 4; } size = tx_size % 4; if (size) { data = 0; memcpy(&data, txbuf, size); data = qspi_endian_xchg(data); qspi_write32(priv->flags, ®s->tbdr, data); } qspi_write32(priv->flags, ®s->ipcr, (seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size); while (qspi_read32(priv->flags, ®s->sr) & QSPI_SR_BUSY_MASK) ; qspi_write32(priv->flags, ®s->mcr, mcr_reg); }