/* * zynq_qspi_start_transfer - Initiates the QSPI transfer * @qspi: Pointer to the spi_device structure * @transfer: Pointer to the spi_transfer structure which provide information * about next transfer parameters * * This function fills the TX FIFO, starts the QSPI transfer, and waits for the * transfer to be completed. * * returns: Number of bytes transferred in the last transfer */ static int zynq_qspi_start_transfer(struct spi_device *qspi, struct spi_transfer *transfer) { struct zynq_qspi *zqspi = &qspi->master; static u8 current_u_page; u32 data = 0; u8 instruction = 0; u8 index; debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__, (u32)qspi, (u32)transfer, transfer->len); zqspi->txbuf = transfer->tx_buf; zqspi->rxbuf = transfer->rx_buf; zqspi->bytes_to_transfer = transfer->len; zqspi->bytes_to_receive = transfer->len; if (zqspi->txbuf) instruction = *(u8 *)zqspi->txbuf; if (instruction && zqspi->is_inst) { for (index = 0; index < ARRAY_SIZE(flash_inst); index++) if (instruction == flash_inst[index].opcode) break; /* * Instruction might have already been transmitted. This is a * 'data only' transfer */ if (index == ARRAY_SIZE(flash_inst)) goto xfer_data; zqspi->curr_inst = &flash_inst[index]; zqspi->inst_response = 1; if ((zqspi->is_dual == MODE_DUAL_STACKED) && (current_u_page != zqspi->u_page)) { if (zqspi->u_page) { /* Configure two memories on shared bus * by enabling upper mem */ writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | ZYNQ_QSPI_LCFG_U_PAGE | (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | ZYNQ_QSPI_FR_QOUT_CODE), &zynq_qspi_base->lcr); } else { /* Configure two memories on shared bus * by enabling lower mem */ writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | ZYNQ_QSPI_FR_QOUT_CODE), &zynq_qspi_base->lcr); } current_u_page = zqspi->u_page; } /* Get the instruction */ data = 0; zynq_qspi_copy_write_data(zqspi, &data, zqspi->curr_inst->inst_size); /* * Write the instruction to LSB of the FIFO. The core is * designed such that it is not necessary to check whether the * write FIFO is full before writing. However, write would be * delayed if the user tries to write when write FIFO is full */ writel(data, &zynq_qspi_base->confr + (zqspi->curr_inst->offset / 4)); /* * Read status register and Read ID instructions don't require * to ignore the extra bytes in response of instruction as * response contains the value */ if ((instruction == ZYNQ_QSPI_FLASH_OPCODE_RDSR1) || (instruction == ZYNQ_QSPI_FLASH_OPCODE_RDSR2) || (instruction == ZYNQ_QSPI_FLASH_OPCODE_RDID) || (instruction == ZYNQ_QSPI_FLASH_OPCODE_BRRD) || (instruction == ZYNQ_QSPI_FLASH_OPCODE_RDEAR)) { if (zqspi->bytes_to_transfer < 4) zqspi->bytes_to_transfer = 0; else zqspi->bytes_to_transfer -= 3; } } xfer_data: /* * In case of Fast, Dual and Quad reads, transmit the instruction first. * Address and dummy byte should be transmitted after instruction * is transmitted */ if (((zqspi->is_inst == 0) && (zqspi->bytes_to_transfer)) || ((zqspi->bytes_to_transfer) && (instruction != ZYNQ_QSPI_FLASH_OPCODE_FR) && (instruction != ZYNQ_QSPI_FLASH_OPCODE_DR) && (instruction != ZYNQ_QSPI_FLASH_OPCODE_QR) && (instruction != ZYNQ_QSPI_FLASH_OPCODE_DIOR))) zynq_qspi_fill_tx_fifo(zqspi, ZYNQ_QSPI_FIFO_DEPTH); writel(ZYNQ_QSPI_IXR_ALL_MASK, &zynq_qspi_base->ier); /* Start the transfer by enabling manual start bit */ /* wait for completion */ do { data = zynq_qspi_irq_poll(zqspi); } while (data == 0); return (transfer->len) - (zqspi->bytes_to_transfer); }
/* * zynq_qspi_start_transfer - Initiates the QSPI transfer * @qspi: Pointer to the spi_device structure * @transfer: Pointer to the spi_transfer structure which provide information * about next transfer parameters * * This function fills the TX FIFO, starts the QSPI transfer, and waits for the * transfer to be completed. * * returns: Number of bytes transferred in the last transfer */ static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv) { static u8 current_u_page; u32 data = 0; struct zynq_qspi_regs *regs = priv->regs; debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__, (u32)priv, (u32)priv, priv->len); priv->bytes_to_transfer = priv->len; priv->bytes_to_receive = priv->len; if (priv->is_inst && (priv->is_dual == SF_DUAL_STACKED_FLASH) && (current_u_page != priv->u_page)) { if (priv->u_page) { if (priv->is_dio == SF_DUALIO_FLASH) writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | ZYNQ_QSPI_LCFG_U_PAGE | (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | ZYNQ_QSPI_FR_DUALIO_CODE), ®s->lcr); else /* Configure two memories on shared bus * by enabling upper mem */ writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | ZYNQ_QSPI_LCFG_U_PAGE | (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | ZYNQ_QSPI_FR_QOUT_CODE), ®s->lcr); } else { if (priv->is_dio == SF_DUALIO_FLASH) writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | ZYNQ_QSPI_FR_DUALIO_CODE), ®s->lcr); else /* Configure two memories on shared bus * by enabling lower mem */ writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | ZYNQ_QSPI_FR_QOUT_CODE), ®s->lcr); } current_u_page = priv->u_page; } if (priv->len < 4) zynq_qspi_fill_tx_fifo(priv, priv->len); else zynq_qspi_fill_tx_fifo(priv, ZYNQ_QSPI_FIFO_DEPTH); writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->ier); /* Start the transfer by enabling manual start bit */ /* wait for completion */ do { data = zynq_qspi_irq_poll(priv); } while (data == 0); return (priv->len) - (priv->bytes_to_transfer); }