/* * The operating mode can be configured based on the command that needs to be send. * bits[15:14]: Sets whether multiple bit SPI operates in normal, extended or full modes. * 00: Normal (single DQ0 TX and single DQ1 RX lines) * 01: Extended RO (command and address bytes on DQ0 only) * 10: Extended RW (command byte on DQ0 only) * 11: Full. (command and address are on all DQ lines) * bit[13]: Sets whether multiple bit SPI uses 2 or 4 bits of data * 0: 2-bits (BSPI) * 1: 4-bits (QSPI)
*/ if (op->data.buswidth == 4 || op->data.buswidth == 2) {
control &= ~CONTROL_MODE12_MASK; if (op->cmd.buswidth == 1 && (op->addr.buswidth == 1 || op->addr.buswidth == 0))
control |= CONTROL_MODE12_EX_RO; elseif (op->cmd.buswidth == 1)
control |= CONTROL_MODE12_EX_RW; else
control |= CONTROL_MODE12_FULL;
control |= CONTROL_MODE0;
} else {
control &= ~(CONTROL_MODE12_MASK |
CONTROL_MODE0);
}
control = readl_relaxed(qspi->regs + REG_CONTROL);
/* * Read 4-bytes from the SPI FIFO in single transaction and then read * the reamaining data byte wise.
*/
control |= CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->rx_len >= 4) { while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
;
data = readl_relaxed(qspi->regs + REG_X4_RX_DATA);
*(u32 *)qspi->rxbuf = data;
qspi->rxbuf += 4;
qspi->rx_len -= 4;
}
control &= ~CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->rx_len--) { while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
;
data = readl_relaxed(qspi->regs + REG_RX_DATA);
*qspi->rxbuf++ = (data & 0xFF);
}
}
control = readl_relaxed(qspi->regs + REG_CONTROL);
control |= CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->tx_len >= 4) { while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_TXFIFOFULL)
;
data = qspi->txbuf ? *((u32 *)qspi->txbuf) : 0xaa; if (qspi->txbuf)
qspi->txbuf += 4;
qspi->tx_len -= 4;
writel_relaxed(data, qspi->regs + REG_X4_TX_DATA);
/* * The rx FIFO is twice the size of the tx FIFO, so there is * no requirement to block transmission if receive data is not * ready, and it is fine to let the tx FIFO completely fill * without reading anything from the rx FIFO. Once the tx FIFO * has been filled and becomes non-full due to a transmission * occurring there will always be something to receive. * IOW, this is safe as TX_FIFO_SIZE + 4 < 2 * TX_FIFO_SIZE
*/ if (qspi->rx_len >= 4) { if (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXAVAILABLE) {
data = readl_relaxed(qspi->regs + REG_X4_RX_DATA);
*(u32 *)qspi->rxbuf = data;
qspi->rxbuf += 4;
qspi->rx_len -= 4;
}
}
}
/* * Since transmission is not being blocked by clearing the rx FIFO, * loop here until all received data "leaked" by the loop above has * been dealt with.
*/ while (qspi->rx_len >= 4) { while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
;
data = readl_relaxed(qspi->regs + REG_X4_RX_DATA);
*(u32 *)qspi->rxbuf = data;
qspi->rxbuf += 4;
qspi->rx_len -= 4;
}
/* * Since rx_len and tx_len must be < 4 bytes at this point, there's no * concern about overflowing the rx or tx FIFOs any longer. It's * therefore safe to loop over the remainder of the transmit data before * handling the remaining receive data.
*/ if (!qspi->tx_len) return;
control &= ~CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->tx_len--) { while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_TXFIFOFULL)
;
data = qspi->txbuf ? *qspi->txbuf : 0xaa;
qspi->txbuf++;
writel_relaxed(data, qspi->regs + REG_TX_DATA);
}
while (qspi->rx_len--) { while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
;
data = readl_relaxed(qspi->regs + REG_RX_DATA);
*qspi->rxbuf++ = (data & 0xFF);
}
}
/* * As per the coreQSPI IP spec,the number of command and data bytes are * controlled by the frames register for each SPI sequence. This supports * the SPI flash memory read and writes sequences as below. so configure * the cmd and total bytes accordingly. * --------------------------------------------------------------------- * TOTAL BYTES | CMD BYTES | What happens | * ______________________________________________________________________ * | | | * 1 | 1 | The SPI core will transmit a single byte | * | | and receive data is discarded | * | | | * 1 | 0 | The SPI core will transmit a single byte | * | | and return a single byte | * | | | * 10 | 4 | The SPI core will transmit 4 command | * | | bytes discarding the receive data and | * | | transmits 6 dummy bytes returning the 6 | * | | received bytes and return a single byte | * | | | * 10 | 10 | The SPI core will transmit 10 command | * | | | * 10 | 0 | The SPI core will transmit 10 command | * | | bytes and returning 10 received bytes | * ______________________________________________________________________
*/ if (!(op->data.dir == SPI_MEM_DATA_IN))
cmd_bytes = total_bytes;
if ((op->data.buswidth == 4 || op->data.buswidth == 2) &&
(op->cmd.buswidth == 1 && (op->addr.buswidth == 1 || op->addr.buswidth == 0))) { /* * If the command and address are on DQ0 only, then this * controller doesn't support sending data on dual and * quad lines. but it supports reading data on dual and * quad lines with same configuration as command and * address on DQ0. * i.e. The control register[15:13] :EX_RO(read only) is * meant only for the command and address are on DQ0 but * not to write data, it is just to read. * Ex: 0x34h is Quad Load Program Data which is not * supported. Then the spi-mem layer will iterate over * each command and it will chose the supported one.
*/ if (op->data.dir == SPI_MEM_DATA_OUT) returnfalse;
}
qspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(qspi->regs)) return dev_err_probe(&pdev->dev, PTR_ERR(qspi->regs), "failed to map registers\n");
qspi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(qspi->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(qspi->clk), "could not get clock\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.