/* * QSPI Configuration Register bit Masks * * This register contains various control bits that effect the operation * of the QSPI controller
*/ #define ZYNQ_QSPI_CONFIG_IFMODE_MASK BIT(31) /* Flash Memory Interface */ #define ZYNQ_QSPI_CONFIG_MANSRT_MASK BIT(16) /* Manual TX Start */ #define ZYNQ_QSPI_CONFIG_MANSRTEN_MASK BIT(15) /* Enable Manual TX Mode */ #define ZYNQ_QSPI_CONFIG_SSFORCE_MASK BIT(14) /* Manual Chip Select */ #define ZYNQ_QSPI_CONFIG_BDRATE_MASK GENMASK(5, 3) /* Baud Rate Mask */ #define ZYNQ_QSPI_CONFIG_CPHA_MASK BIT(2) /* Clock Phase Control */ #define ZYNQ_QSPI_CONFIG_CPOL_MASK BIT(1) /* Clock Polarity Control */ #define ZYNQ_QSPI_CONFIG_FWIDTH_MASK GENMASK(7, 6) /* FIFO width */ #define ZYNQ_QSPI_CONFIG_MSTREN_MASK BIT(0) /* Master Mode */
/* * QSPI Configuration Register - Baud rate and target select * * These are the values used in the calculation of baud rate divisor and * setting the target select.
*/ #define ZYNQ_QSPI_CONFIG_BAUD_DIV_MAX GENMASK(2, 0) /* Baud rate maximum */ #define ZYNQ_QSPI_CONFIG_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift */ #define ZYNQ_QSPI_CONFIG_PCS BIT(10) /* Peripheral Chip Select */
/* * QSPI Interrupt Registers bit Masks * * All the four interrupt registers (Status/Mask/Enable/Disable) have the same * bit definitions.
*/ #define ZYNQ_QSPI_IXR_RX_OVERFLOW_MASK BIT(0) /* QSPI RX FIFO Overflow */ #define ZYNQ_QSPI_IXR_TXNFULL_MASK BIT(2) /* QSPI TX FIFO Overflow */ #define ZYNQ_QSPI_IXR_TXFULL_MASK BIT(3) /* QSPI TX FIFO is full */ #define ZYNQ_QSPI_IXR_RXNEMTY_MASK BIT(4) /* QSPI RX FIFO Not Empty */ #define ZYNQ_QSPI_IXR_RXF_FULL_MASK BIT(5) /* QSPI RX FIFO is full */ #define ZYNQ_QSPI_IXR_TXF_UNDRFLOW_MASK BIT(6) /* QSPI TX FIFO Underflow */ #define ZYNQ_QSPI_IXR_ALL_MASK (ZYNQ_QSPI_IXR_RX_OVERFLOW_MASK | \
ZYNQ_QSPI_IXR_TXNFULL_MASK | \
ZYNQ_QSPI_IXR_TXFULL_MASK | \
ZYNQ_QSPI_IXR_RXNEMTY_MASK | \
ZYNQ_QSPI_IXR_RXF_FULL_MASK | \
ZYNQ_QSPI_IXR_TXF_UNDRFLOW_MASK) #define ZYNQ_QSPI_IXR_RXTX_MASK (ZYNQ_QSPI_IXR_TXNFULL_MASK | \
ZYNQ_QSPI_IXR_RXNEMTY_MASK)
/* * QSPI Enable Register bit Masks * * This register is used to enable or disable the QSPI controller
*/ #define ZYNQ_QSPI_ENABLE_ENABLE_MASK BIT(0) /* QSPI Enable Bit Mask */
/* * QSPI Linear Configuration Register * * It is named Linear Configuration but it controls other modes when not in * linear mode also.
*/ #define ZYNQ_QSPI_LCFG_TWO_MEM BIT(30) /* LQSPI Two memories */ #define ZYNQ_QSPI_LCFG_SEP_BUS BIT(29) /* LQSPI Separate bus */ #define ZYNQ_QSPI_LCFG_U_PAGE BIT(28) /* LQSPI Upper Page */
/* * The modebits configurable by the driver to make the SPI support different * data formats
*/ #define ZYNQ_QSPI_MODEBITS (SPI_CPOL | SPI_CPHA)
/* Maximum number of chip selects */ #define ZYNQ_QSPI_MAX_NUM_CS 2
/** * struct zynq_qspi - Defines qspi driver instance * @dev: Pointer to the this device's information * @regs: Virtual address of the QSPI controller registers * @refclk: Pointer to the peripheral clock * @pclk: Pointer to the APB clock * @irq: IRQ number * @txbuf: Pointer to the TX buffer * @rxbuf: Pointer to the RX buffer * @tx_bytes: Number of bytes left to transfer * @rx_bytes: Number of bytes left to receive * @data_completion: completion structure
*/ struct zynq_qspi { struct device *dev; void __iomem *regs; struct clk *refclk; struct clk *pclk; int irq;
u8 *txbuf;
u8 *rxbuf; int tx_bytes; int rx_bytes; struct completion data_completion;
};
/** * zynq_qspi_init_hw - Initialize the hardware * @xqspi: Pointer to the zynq_qspi structure * @num_cs: Number of connected CS (to enable dual memories if needed) * * The default settings of the QSPI controller's configurable parameters on * reset are * - Host mode * - Baud rate divisor is set to 2 * - Tx threshold set to 1l Rx threshold set to 32 * - Flash memory interface mode enabled * - Size of the word to be transferred as 8 bit * This function performs the following actions * - Disable and clear all the interrupts * - Enable manual target select * - Enable manual start * - Deselect all the chip select lines * - Set the size of the word to be transferred as 32 bit * - Set the little endian mode of TX FIFO and * - Enable the QSPI controller
*/ staticvoid zynq_qspi_init_hw(struct zynq_qspi *xqspi, unsignedint num_cs)
{
u32 config_reg;
/* Disable linear mode as the boot loader may have used it */
config_reg = 0; /* At the same time, enable dual mode if more than 1 CS is available */ if (num_cs > 1)
config_reg |= ZYNQ_QSPI_LCFG_TWO_MEM;
/* * The number of address bytes should be equal to or less than 3 bytes.
*/ if (op->addr.nbytes > 3) returnfalse;
returntrue;
}
/** * zynq_qspi_rxfifo_op - Read 1..4 bytes from RxFIFO to RX buffer * @xqspi: Pointer to the zynq_qspi structure * @size: Number of bytes to be read (1..4)
*/ staticvoid zynq_qspi_rxfifo_op(struct zynq_qspi *xqspi, unsignedint size)
{
u32 data;
data = zynq_qspi_read(xqspi, ZYNQ_QSPI_RXD_OFFSET);
/* Ground the line to assert the CS */
config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_CONFIG_OFFSET); if (assert)
config_reg &= ~ZYNQ_QSPI_CONFIG_PCS; else
config_reg |= ZYNQ_QSPI_CONFIG_PCS;
/** * zynq_qspi_config_op - Configure QSPI controller for specified transfer * @xqspi: Pointer to the zynq_qspi structure * @spi: Pointer to the spi_device structure * @op: The memory operation to execute * * Sets the operational mode of QSPI controller for the next QSPI transfer and * sets the requested clock frequency. * * Return: 0 on success and -EINVAL on invalid input parameter * * Note: If the requested frequency is not an exact match with what can be * obtained using the prescalar value, the driver sets the clock frequency which * is lower than the requested frequency (maximum lower) for the transfer. If * the requested frequency is higher or lower than that is supported by the QSPI * controller the driver will set the highest or lowest frequency supported by * controller.
*/ staticint zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi, conststruct spi_mem_op *op)
{
u32 config_reg, baud_rate_val = 0;
/* * Set the clock frequency * The baud rate divisor is not a direct mapping to the value written * into the configuration register (config_reg[5:3]) * i.e. 000 - divide by 2 * 001 - divide by 4 * ---------------- * 111 - divide by 256
*/ while ((baud_rate_val < ZYNQ_QSPI_CONFIG_BAUD_DIV_MAX) &&
(clk_get_rate(xqspi->refclk) / (2 << baud_rate_val)) >
op->max_freq)
baud_rate_val++;
/** * zynq_qspi_setup_op - Configure the QSPI controller * @spi: Pointer to the spi_device structure * * Sets the operational mode of QSPI controller for the next QSPI transfer, baud * rate and divisor value to setup the requested qspi clock. * * Return: 0 on success and error value on failure
*/ staticint zynq_qspi_setup_op(struct spi_device *spi)
{ struct spi_controller *ctlr = spi->controller; struct zynq_qspi *qspi = spi_controller_get_devdata(ctlr); int ret;
if (ctlr->busy) return -EBUSY;
ret = clk_enable(qspi->refclk); if (ret) return ret;
ret = clk_enable(qspi->pclk); if (ret) {
clk_disable(qspi->refclk); return ret;
}
/** * zynq_qspi_write_op - Fills the TX FIFO with as many bytes as possible * @xqspi: Pointer to the zynq_qspi structure * @txcount: Maximum number of words to write * @txempty: Indicates that TxFIFO is empty
*/ staticvoid zynq_qspi_write_op(struct zynq_qspi *xqspi, int txcount, bool txempty)
{ int count, len, k;
len = xqspi->tx_bytes; if (len && len < 4) { /* * We must empty the TxFIFO between accesses to TXD0, * TXD1, TXD2, TXD3.
*/ if (txempty)
zynq_qspi_txfifo_op(xqspi, len);
return;
}
count = len / 4; if (count > txcount)
count = txcount;
if (xqspi->txbuf) {
iowrite32_rep(xqspi->regs + ZYNQ_QSPI_TXD_00_00_OFFSET,
xqspi->txbuf, count);
xqspi->txbuf += count * 4;
} else { for (k = 0; k < count; k++)
writel_relaxed(0, xqspi->regs +
ZYNQ_QSPI_TXD_00_00_OFFSET);
}
xqspi->tx_bytes -= count * 4;
}
/** * zynq_qspi_read_op - Drains the RX FIFO by as many bytes as possible * @xqspi: Pointer to the zynq_qspi structure * @rxcount: Maximum number of words to read
*/ staticvoid zynq_qspi_read_op(struct zynq_qspi *xqspi, int rxcount)
{ int count, len, k;
len = xqspi->rx_bytes - xqspi->tx_bytes;
count = len / 4; if (count > rxcount)
count = rxcount; if (xqspi->rxbuf) {
ioread32_rep(xqspi->regs + ZYNQ_QSPI_RXD_OFFSET,
xqspi->rxbuf, count);
xqspi->rxbuf += count * 4;
} else { for (k = 0; k < count; k++)
readl_relaxed(xqspi->regs + ZYNQ_QSPI_RXD_OFFSET);
}
xqspi->rx_bytes -= count * 4;
len -= count * 4;
if (len && len < 4 && count < rxcount)
zynq_qspi_rxfifo_op(xqspi, len);
}
/** * zynq_qspi_irq - Interrupt service routine of the QSPI controller * @irq: IRQ number * @dev_id: Pointer to the xqspi structure * * This function handles TX empty only. * On TX empty interrupt this function reads the received data from RX FIFO and * fills the TX FIFO if there is any data remaining to be transferred. * * Return: IRQ_HANDLED when interrupt is handled; IRQ_NONE otherwise.
*/ static irqreturn_t zynq_qspi_irq(int irq, void *dev_id)
{
u32 intr_status; bool txempty; struct zynq_qspi *xqspi = (struct zynq_qspi *)dev_id;
if ((intr_status & ZYNQ_QSPI_IXR_TXNFULL_MASK) ||
(intr_status & ZYNQ_QSPI_IXR_RXNEMTY_MASK)) { /* * This bit is set when Tx FIFO has < THRESHOLD entries. * We have the THRESHOLD value set to 1, * so this bit indicates Tx FIFO is empty.
*/
txempty = !!(intr_status & ZYNQ_QSPI_IXR_TXNFULL_MASK); /* Read out the data from the RX FIFO */
zynq_qspi_read_op(xqspi, ZYNQ_QSPI_RX_THRESHOLD); if (xqspi->tx_bytes) { /* There is more data to send */
zynq_qspi_write_op(xqspi, ZYNQ_QSPI_RX_THRESHOLD,
txempty);
} else { /* * If transfer and receive is completed then only send * complete signal.
*/ if (!xqspi->rx_bytes) {
zynq_qspi_write(xqspi,
ZYNQ_QSPI_IDIS_OFFSET,
ZYNQ_QSPI_IXR_RXTX_MASK);
complete(&xqspi->data_completion);
}
} return IRQ_HANDLED;
}
return IRQ_NONE;
}
/** * zynq_qspi_exec_mem_op() - Initiates the QSPI transfer * @mem: the SPI memory * @op: the memory operation to execute * * Executes a memory operation. * * This function first selects the chip and starts the memory operation. * * Return: 0 in case of success, a negative error code otherwise.
*/ staticint zynq_qspi_exec_mem_op(struct spi_mem *mem, conststruct spi_mem_op *op)
{ struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->controller); int err = 0, i;
u8 *tmpbuf;
/** * zynq_qspi_probe - Probe method for the QSPI driver * @pdev: Pointer to the platform_device structure * * This function initializes the driver data structures and the hardware. * * Return: 0 on success and error value on failure
*/ staticint zynq_qspi_probe(struct platform_device *pdev)
{ int ret = 0; struct spi_controller *ctlr; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct zynq_qspi *xqspi;
u32 num_cs;
ctlr = spi_alloc_host(&pdev->dev, sizeof(*xqspi)); if (!ctlr) return -ENOMEM;
/** * zynq_qspi_remove - Remove method for the QSPI driver * @pdev: Pointer to the platform_device structure * * This function is called if a device is physically removed from the system or * if the driver module is being unloaded. It frees all resources allocated to * the device. * * Return: 0 on success and error value on failure
*/ staticvoid zynq_qspi_remove(struct platform_device *pdev)
{ struct zynq_qspi *xqspi = platform_get_drvdata(pdev);
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.