diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 15 | ||||
-rw-r--r-- | drivers/spi/spi-mem.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-xilinx.c | 1055 | ||||
-rw-r--r-- | drivers/spi/spi-zynq-qspi.c | 43 | ||||
-rw-r--r-- | drivers/spi/spi-zynqmp-gqspi.c | 402 | ||||
-rw-r--r-- | drivers/spi/spi.c | 8 |
6 files changed, 1132 insertions, 393 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 30a40280c157..f6971237b7cc 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -851,11 +851,18 @@ config SPI_XTENSA_XTFPGA config SPI_ZYNQ_QSPI tristate "Xilinx Zynq QSPI controller" - depends on ARCH_ZYNQ || COMPILE_TEST + depends on ARCH_ZYNQ + depends on SPI_MASTER help - This enables support for the Zynq Quad SPI controller - in master mode. - This controller only supports SPI memory interface. + This selects the Xilinx ZYNQ Quad SPI controller master driver. + +config SPI_ZYNQ_QSPI_DUAL_STACKED + bool "Xilinx Zynq QSPI Dual stacked configuration" + depends on SPI_ZYNQ_QSPI + help + This selects the Xilinx ZYNQ Quad SPI controller in dual stacked mode. + Enable this option if your hw design is using dual stacked + configuration. config SPI_ZYNQMP_GQSPI tristate "Xilinx ZynqMP GQSPI controller" diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index de0ba3e5449f..550f3ff36fa3 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -348,6 +348,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) xfers[xferpos].tx_buf = tmpbuf + op->addr.nbytes + 1; xfers[xferpos].len = op->dummy.nbytes; xfers[xferpos].tx_nbits = op->dummy.buswidth; + xfers[xferpos].dummy = op->dummy.nbytes * 8; spi_message_add_tail(&xfers[xferpos], &msg); xferpos++; totalxferlen += op->dummy.nbytes; @@ -362,6 +363,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) xfers[xferpos].tx_nbits = op->data.buswidth; } + xfers[xferpos].stripe = update_stripe(op->cmd.opcode); xfers[xferpos].len = op->data.nbytes; spi_message_add_tail(&xfers[xferpos], &msg); xferpos++; diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index d5f9d5fbb3e8..b3d2cc5cb6ec 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -16,10 +16,11 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> -#include <linux/spi/spi_bitbang.h> #include <linux/spi/xilinx_spi.h> #include <linux/io.h> - +#include <linux/delay.h> +#include <linux/pm_runtime.h> +#include <linux/clk.h> #define XILINX_SPI_MAX_CS 32 #define XILINX_SPI_NAME "xilinx_spi" @@ -27,8 +28,18 @@ /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) * Product Specification", DS464 */ -#define XSPI_CR_OFFSET 0x60 /* Control Register */ - +/* Register Offsets */ +#define XSPI_CR_OFFSET 0x60 +#define XSPI_SR_OFFSET 0x64 +#define XSPI_TXD_OFFSET 0x68 +#define XSPI_RXD_OFFSET 0x6c +#define XSPI_SSR_OFFSET 0x70 +#define XIPIF_V123B_DGIER_OFFSET 0x1c +#define XIPIF_V123B_IISR_OFFSET 0x20 +#define XIPIF_V123B_IIER_OFFSET 0x28 +#define XIPIF_V123B_RESETR_OFFSET 0x40 + +/* Register bit masks */ #define XSPI_CR_LOOP 0x01 #define XSPI_CR_ENABLE 0x02 #define XSPI_CR_MASTER_MODE 0x04 @@ -41,133 +52,203 @@ #define XSPI_CR_MANUAL_SSELECT 0x80 #define XSPI_CR_TRANS_INHIBIT 0x100 #define XSPI_CR_LSB_FIRST 0x200 - -#define XSPI_SR_OFFSET 0x64 /* Status Register */ - -#define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */ -#define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */ -#define XSPI_SR_TX_EMPTY_MASK 0x04 /* Transmit FIFO is empty */ -#define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */ -#define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */ - -#define XSPI_TXD_OFFSET 0x68 /* Data Transmit Register */ -#define XSPI_RXD_OFFSET 0x6c /* Data Receive Register */ - -#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */ - -/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414 - * IPIF registers are 32 bit - */ -#define XIPIF_V123B_DGIER_OFFSET 0x1c /* IPIF global int enable reg */ +#define XSPI_SR_RX_EMPTY_MASK 0x01 +#define XSPI_SR_RX_FULL_MASK 0x02 +#define XSPI_SR_TX_EMPTY_MASK 0x04 +#define XSPI_SR_TX_FULL_MASK 0x08 +#define XSPI_SR_MODE_FAULT_MASK 0x10 #define XIPIF_V123B_GINTR_ENABLE 0x80000000 - -#define XIPIF_V123B_IISR_OFFSET 0x20 /* IPIF interrupt status reg */ -#define XIPIF_V123B_IIER_OFFSET 0x28 /* IPIF interrupt enable reg */ - -#define XSPI_INTR_MODE_FAULT 0x01 /* Mode fault error */ -#define XSPI_INTR_SLAVE_MODE_FAULT 0x02 /* Selected as slave while - * disabled */ -#define XSPI_INTR_TX_EMPTY 0x04 /* TxFIFO is empty */ -#define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */ -#define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */ -#define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */ -#define XSPI_INTR_TX_HALF_EMPTY 0x40 /* TxFIFO is half empty */ - -#define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */ -#define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */ - +#define XSPI_INTR_MODE_FAULT 0x01 +#define XSPI_INTR_SLAVE_MODE_FAULT 0x02 +#define XSPI_INTR_TX_EMPTY 0x04 +#define XSPI_INTR_TX_UNDERRUN 0x08 +#define XSPI_INTR_RX_FULL 0x10 +#define XSPI_INTR_RX_OVERRUN 0x20 +#define XSPI_INTR_TX_HALF_EMPTY 0x40 +#define XIPIF_V123B_RESET_MASK 0x0a + +/* Number of bits per word */ +#define XSPI_ONE_BITS_PER_WORD 1 +#define XSPI_TWO_BITS_PER_WORD 2 +#define XSPI_FOUR_BITS_PER_WORD 4 + +/* Number of data lines used to receive */ +#define XSPI_RX_ONE_WIRE 1 +#define XSPI_RX_FOUR_WIRE 4 + +/* Auto suspend timeout in milliseconds */ +#define SPI_AUTOSUSPEND_TIMEOUT 3000 + +/* Command used for Dummy read Id */ +#define SPI_READ_ID 0x9F + +/** + * struct xilinx_spi - This definition define spi driver instance + * @regs: virt. address of the control registers + * @irq: IRQ number + * @axi_clk: Pointer to the AXI clock + * @axi4_clk: Pointer to the AXI4 clock + * @spi_clk: Pointer to the SPI clock + * @dev: Pointer to the device + * @rx_ptr: Pointer to the RX buffer + * @tx_ptr: Pointer to the TX buffer + * @bytes_per_word: Number of bytes in a word + * @buffer_size: Buffer size in words + * @cs_inactive: Level of the CS pins when inactive + * @read_fn: For reading data from SPI registers + * @write_fn: For writing data to SPI registers + * @bytes_to_transfer: Number of bytes left to transfer + * @bytes_to_receive: Number of bytes left to receive + * @rx_bus_width: Number of wires used to receive data + * @tx_fifo: For writing data to fifo + * @rx_fifo: For reading data from fifo + */ struct xilinx_spi { - /* bitbang has to be first */ - struct spi_bitbang bitbang; - struct completion done; - void __iomem *regs; /* virt. address of the control registers */ - - int irq; - - u8 *rx_ptr; /* pointer in the Tx buffer */ - const u8 *tx_ptr; /* pointer in the Rx buffer */ + void __iomem *regs; + int irq; + struct clk *axi_clk; + struct clk *axi4_clk; + struct clk *spi_clk; + struct device *dev; + u8 *rx_ptr; + const u8 *tx_ptr; u8 bytes_per_word; - int buffer_size; /* buffer size in words */ - u32 cs_inactive; /* Level of the CS pins when inactive*/ - unsigned int (*read_fn)(void __iomem *); - void (*write_fn)(u32, void __iomem *); + int buffer_size; + u32 cs_inactive; + unsigned int (*read_fn)(void __iomem *addr); + void (*write_fn)(u32, void __iomem *addr); + u32 bytes_to_transfer; + u32 bytes_to_receive; + u32 rx_bus_width; + void (*tx_fifo)(struct xilinx_spi *xqspi); + void (*rx_fifo)(struct xilinx_spi *xqspi); }; +/** + * XSPI_FIFO_READ - Generate xspi_read_rx_fifo_* functions + * @size: bits_per_word that are read from RX FIFO + * @type: C type of value argument + * + * Generates xspi_read_rx_fifo_* functions used to write + * data into RX FIFO for different transaction widths. + */ +#define XSPI_FIFO_READ(size, type) \ +static void xspi_read_rx_fifo_##size(struct xilinx_spi *xqspi) \ +{ \ + int i; \ + int count = (xqspi->bytes_to_receive > xqspi->buffer_size) ? \ + xqspi->buffer_size : xqspi->bytes_to_receive; \ + u32 data; \ + for (i = 0; i < count; i += (size/8)) { \ + data = readl_relaxed(xqspi->regs + XSPI_RXD_OFFSET); \ + if (xqspi->rx_ptr) \ + ((type *)xqspi->rx_ptr)[i] = (type)data; \ + } \ + xqspi->bytes_to_receive -= count; \ + if (xqspi->rx_ptr) \ + xqspi->rx_ptr += count; \ +} + +/** + * XSPI_FIFO_WRITE - Generate xspi_fill_tx_fifo_* functions + * @size: bits_per_word that are written into TX FIFO + * @type: C type of value argument + * + * Generates xspi_fill_tx_fifo_* functions used to write + * data into TX FIFO for different transaction widths. + */ +#define XSPI_FIFO_WRITE(size, type) \ +static void xspi_fill_tx_fifo_##size(struct xilinx_spi *xqspi) \ +{ \ + int i; \ + int count = (xqspi->bytes_to_transfer > xqspi->buffer_size) ? \ + xqspi->buffer_size : xqspi->bytes_to_transfer; \ + u32 data = 0; \ + for (i = 0; i < count; i += (size/8)) { \ + if (xqspi->tx_ptr) \ + data = (type)((u8 *)xqspi->tx_ptr)[i]; \ + writel_relaxed(data, (xqspi->regs + XSPI_TXD_OFFSET)); \ + } \ + xqspi->bytes_to_transfer -= count; \ + if (xqspi->tx_ptr) \ + xqspi->tx_ptr += count; \ +} + +XSPI_FIFO_READ(8, u8) +XSPI_FIFO_READ(16, u16) +XSPI_FIFO_READ(32, u32) +XSPI_FIFO_WRITE(8, u8) +XSPI_FIFO_WRITE(16, u16) +XSPI_FIFO_WRITE(32, u32) + +/** + * xspi_write32 - Write a value to the device register little endian + * @val: Value to write at the Register offset + * @addr: Register offset + * + * Write data to the paricular SPI register + */ static void xspi_write32(u32 val, void __iomem *addr) { iowrite32(val, addr); } +/** + * xspi_read32 - read a value from the device register little endian + * @addr: Register offset + * + * Read data from the paricular SPI register + * + * Return: return value from the SPI register. + */ static unsigned int xspi_read32(void __iomem *addr) { return ioread32(addr); } +/** + * xspi_write32_be - Write a value to the device register big endian + * @val: Value to write at the Register offset + * @addr: Register offset + * + * Write data to the paricular SPI register + */ static void xspi_write32_be(u32 val, void __iomem *addr) { iowrite32be(val, addr); } +/** + * xspi_read32_be - read a value from the device register big endian + * @addr: Register offset + * + * Read data from the paricular SPI register + * + * Return: return value from the SPI register. + */ static unsigned int xspi_read32_be(void __iomem *addr) { return ioread32be(addr); } -static void xilinx_spi_tx(struct xilinx_spi *xspi) -{ - u32 data = 0; - - if (!xspi->tx_ptr) { - xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); - return; - } - - switch (xspi->bytes_per_word) { - case 1: - data = *(u8 *)(xspi->tx_ptr); - break; - case 2: - data = *(u16 *)(xspi->tx_ptr); - break; - case 4: - data = *(u32 *)(xspi->tx_ptr); - break; - } - - xspi->write_fn(data, xspi->regs + XSPI_TXD_OFFSET); - xspi->tx_ptr += xspi->bytes_per_word; -} - -static void xilinx_spi_rx(struct xilinx_spi *xspi) -{ - u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); - - if (!xspi->rx_ptr) - return; - - switch (xspi->bytes_per_word) { - case 1: - *(u8 *)(xspi->rx_ptr) = data; - break; - case 2: - *(u16 *)(xspi->rx_ptr) = data; - break; - case 4: - *(u32 *)(xspi->rx_ptr) = data; - break; - } - - xspi->rx_ptr += xspi->bytes_per_word; -} - +/** + * xspi_init_hw - Initialize the hardware + * @xspi: Pointer to the zynqmp_qspi structure + * + * This function performs the following actions + * - Disable and clear all the interrupts + * - Enable manual slave select + * - Enable the SPI controller + */ static void xspi_init_hw(struct xilinx_spi *xspi) { void __iomem *regs_base = xspi->regs; /* Reset the SPI device */ xspi->write_fn(XIPIF_V123B_RESET_MASK, - regs_base + XIPIF_V123B_RESETR_OFFSET); - /* Enable the transmit empty interrupt, which we use to determine + regs_base + XIPIF_V123B_RESETR_OFFSET); + /* + * Enable the transmit empty interrupt, which we use to determine * progress on the transmission. */ xspi->write_fn(XSPI_INTR_TX_EMPTY, @@ -176,262 +257,457 @@ static void xspi_init_hw(struct xilinx_spi *xspi) xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); /* Deselect the slave on the SPI bus */ xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET); - /* Disable the transmitter, enable Manual Slave Select Assertion, - * put SPI controller into master mode, and enable it */ + /* + * Disable the transmitter, enable Manual Slave Select Assertion, + * put SPI controller into master mode, and enable it + */ xspi->write_fn(XSPI_CR_MANUAL_SSELECT | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET | XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET); } -static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) +/** + * xspi_chipselect - Select or deselect the chip select line + * @qspi: Pointer to the spi_device structure + * @is_high: Select(0) or deselect (1) the chip select line + * + */ +static void xspi_chipselect(struct spi_device *qspi, bool is_high) { - struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); - u16 cr; + struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master); u32 cs; - if (is_on == BITBANG_CS_INACTIVE) { - /* Deselect the slave on the SPI bus */ - xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET); - return; + if (is_high) { + /* Deselect the slave */ + xqspi->write_fn(xqspi->cs_inactive, + xqspi->regs + XSPI_SSR_OFFSET); + } else { + cs = xqspi->cs_inactive; + cs ^= BIT(qspi->chip_select); + /* Activate the chip select */ + xqspi->write_fn(cs, xqspi->regs + XSPI_SSR_OFFSET); } +} - /* Set the SPI clock phase and polarity */ - cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_MODE_MASK; - if (spi->mode & SPI_CPHA) - cr |= XSPI_CR_CPHA; - if (spi->mode & SPI_CPOL) - cr |= XSPI_CR_CPOL; - if (spi->mode & SPI_LSB_FIRST) - cr |= XSPI_CR_LSB_FIRST; - if (spi->mode & SPI_LOOP) - cr |= XSPI_CR_LOOP; - xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); - - /* We do not check spi->max_speed_hz here as the SPI clock - * frequency is not software programmable (the IP block design - * parameter) - */ +/** + * xilinx_spi_irq - Interrupt service routine of the SPI controller + * @irq: IRQ number + * @dev_id: Pointer to the xspi 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 xilinx_spi_irq(int irq, void *dev_id) +{ + struct spi_master *master = dev_id; + struct xilinx_spi *xspi = spi_master_get_devdata(dev_id); + u32 ipif_isr; + int status = IRQ_NONE; - cs = xspi->cs_inactive; - cs ^= BIT(spi->chip_select); + /* Get the IPIF interrupts, and clear them immediately */ + ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); + xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET); + if (ipif_isr & XSPI_INTR_TX_EMPTY) { + /* Transmission completed */ + xspi->rx_fifo(xspi); + if (xspi->bytes_to_transfer) { + /* There is more data to send */ + xspi->tx_fifo(xspi); + } + status = IRQ_HANDLED; + } - /* Activate the chip select */ - xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET); + if (!xspi->bytes_to_receive && !xspi->bytes_to_transfer) { + spi_finalize_current_transfer(master); + /* Disable the interrupts here. */ + xspi->write_fn(0x0, xspi->regs + XIPIF_V123B_DGIER_OFFSET); + } + + return status; } -/* spi_bitbang requires custom setup_transfer() to be defined if there is a - * custom txrx_bufs(). +/** + * xilinx_spi_startup_block - Perform a dummy read as a + * work around for the startup block issue in the spi controller. + * @xspi: Pointer to the xilinx_spi structure + * @cs_num: chip select number. + * + * Perform a dummy read if startup block is enabled in the + * spi controller. + * + * Return: None */ -static int xilinx_spi_setup_transfer(struct spi_device *spi, - struct spi_transfer *t) +static void xilinx_spi_startup_block(struct xilinx_spi *xspi, u32 cs_num) { - struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); + void __iomem *regs_base = xspi->regs; + u32 chip_sel, config_reg, status_reg; - if (spi->mode & SPI_CS_HIGH) - xspi->cs_inactive &= ~BIT(spi->chip_select); + /* Activate the chip select */ + chip_sel = xspi->cs_inactive; + chip_sel ^= BIT(cs_num); + xspi->write_fn(chip_sel, regs_base + XSPI_SSR_OFFSET); + + /* Write ReadId to the TXD register */ + xspi->write_fn(SPI_READ_ID, regs_base + XSPI_TXD_OFFSET); + xspi->write_fn(0x0, regs_base + XSPI_TXD_OFFSET); + xspi->write_fn(0x0, regs_base + XSPI_TXD_OFFSET); + + config_reg = xspi->read_fn(regs_base + XSPI_CR_OFFSET); + /* Enable master transaction */ + config_reg &= ~XSPI_CR_TRANS_INHIBIT; + xspi->write_fn(config_reg, regs_base + XSPI_CR_OFFSET); + + status_reg = xspi->read_fn(regs_base + XSPI_SR_OFFSET); + while ((status_reg & XSPI_SR_TX_EMPTY_MASK) == 0) + status_reg = xspi->read_fn(regs_base + XSPI_SR_OFFSET); + + /* Disable master transaction */ + config_reg |= XSPI_CR_TRANS_INHIBIT; + xspi->write_fn(config_reg, regs_base + XSPI_CR_OFFSET); + + /* Read the RXD Register */ + status_reg = xspi->read_fn(regs_base + XSPI_SR_OFFSET); + while ((status_reg & XSPI_SR_RX_EMPTY_MASK) == 0) { + xspi->read_fn(regs_base + XSPI_RXD_OFFSET); + status_reg = xspi->read_fn(regs_base + XSPI_SR_OFFSET); + } + + xspi_init_hw(xspi); +} + +/** + * xspi_setup_transfer - Configure SPI controller for specified + * transfer + * @qspi: Pointer to the spi_device structure + * @transfer: Pointer to the spi_transfer structure which provides + * information about next transfer setup parameters + * + * Sets the operational mode of QSPI controller for the next QSPI + * transfer. + * + * Return: 0 always + */ +static int xspi_setup_transfer(struct spi_device *qspi, + struct spi_transfer *transfer) +{ + struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master); + u32 config_reg; + + config_reg = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET); + /* Set the QSPI clock phase and clock polarity */ + config_reg &= ~(XSPI_CR_CPHA | XSPI_CR_CPOL); + if (qspi->mode & SPI_CPHA) + config_reg |= XSPI_CR_CPHA; + if (qspi->mode & SPI_CPOL) + config_reg |= XSPI_CR_CPOL; + if (qspi->mode & SPI_LSB_FIRST) + config_reg |= XSPI_CR_LSB_FIRST; + xqspi->write_fn(config_reg, xqspi->regs + XSPI_CR_OFFSET); + + if (qspi->mode & SPI_CS_HIGH) + xqspi->cs_inactive &= ~BIT(qspi->chip_select); else - xspi->cs_inactive |= BIT(spi->chip_select); + xqspi->cs_inactive |= BIT(qspi->chip_select); return 0; } -static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) +/** + * xspi_setup - Configure the SPI controller + * @qspi: Pointer to the spi_device structure + * + * Sets the operational mode of QSPI controller for the next QSPI + * transfer. + * + * Return: 0 on success; error value otherwise. + */ +static int xspi_setup(struct spi_device *qspi) +{ + int ret; + struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master); + + if (qspi->master->busy) + return -EBUSY; + + ret = pm_runtime_get_sync(xqspi->dev); + if (ret < 0) + return ret; + + ret = xspi_setup_transfer(qspi, NULL); + pm_runtime_put_sync(xqspi->dev); + + return ret; +} + +/** + * xspi_start_transfer - Initiates the SPI transfer + * @master: Pointer to the spi_master structure which provides + * information about the controller. + * @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 SPI transfer, and waits for the + * transfer to be completed. + * + * Return: Number of bytes transferred in the last transfer + */ + +static int xspi_start_transfer(struct spi_master *master, + struct spi_device *qspi, + struct spi_transfer *transfer) { - struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); - int remaining_words; /* the number of words left to transfer */ - bool use_irq = false; - u16 cr = 0; - - /* We get here with transmitter inhibited */ - - xspi->tx_ptr = t->tx_buf; - xspi->rx_ptr = t->rx_buf; - remaining_words = t->len / xspi->bytes_per_word; - - if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) { - u32 isr; - use_irq = true; - /* Inhibit irq to avoid spurious irqs on tx_empty*/ - cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); - xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, - xspi->regs + XSPI_CR_OFFSET); - /* ACK old irqs (if any) */ - isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); - if (isr) - xspi->write_fn(isr, - xspi->regs + XIPIF_V123B_IISR_OFFSET); - /* Enable the global IPIF interrupt */ - xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, - xspi->regs + XIPIF_V123B_DGIER_OFFSET); - reinit_completion(&xspi->done); + struct xilinx_spi *xqspi = spi_master_get_devdata(master); + u32 cr; + + xqspi->tx_ptr = transfer->tx_buf; + xqspi->rx_ptr = transfer->rx_buf; + + if (transfer->dummy) { + xqspi->bytes_to_transfer = (transfer->len - (transfer->dummy/8)) + + ((transfer->dummy/8) * + xqspi->rx_bus_width); + xqspi->bytes_to_receive = (transfer->len - (transfer->dummy/8)) + + ((transfer->dummy/8) * + xqspi->rx_bus_width); + } else { + xqspi->bytes_to_transfer = transfer->len; + xqspi->bytes_to_receive = transfer->len; } - while (remaining_words) { - int n_words, tx_words, rx_words; - u32 sr; - int stalled; + xspi_setup_transfer(qspi, transfer); + cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET); + /* Enable master transaction inhibit */ + cr |= XSPI_CR_TRANS_INHIBIT; + xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET); + xqspi->tx_fifo(xqspi); + /* Disable master transaction inhibit */ + cr &= ~XSPI_CR_TRANS_INHIBIT; + xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET); + xqspi->write_fn(XIPIF_V123B_GINTR_ENABLE, + xqspi->regs + XIPIF_V123B_DGIER_OFFSET); + + return transfer->len; +} - n_words = min(remaining_words, xspi->buffer_size); +/** + * xspi_prepare_transfer_hardware - Prepares hardware for transfer. + * @master: Pointer to the spi_master structure which provides + * information about the controller. + * + * This function enables SPI master controller. + * + * Return: 0 on success; error value otherwise + */ +static int xspi_prepare_transfer_hardware(struct spi_master *master) +{ + struct xilinx_spi *xqspi = spi_master_get_devdata(master); - tx_words = n_words; - while (tx_words--) - xilinx_spi_tx(xspi); + u32 cr; + int ret; - /* Start the transfer by not inhibiting the transmitter any - * longer - */ + ret = pm_runtime_get_sync(xqspi->dev); + if (ret < 0) + return ret; - if (use_irq) { - xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); - wait_for_completion(&xspi->done); - /* A transmit has just completed. Process received data - * and check for more data to transmit. Always inhibit - * the transmitter while the Isr refills the transmit - * register/FIFO, or make sure it is stopped if we're - * done. - */ - xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, - xspi->regs + XSPI_CR_OFFSET); - sr = XSPI_SR_TX_EMPTY_MASK; - } else - sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); - - /* Read out all the data from the Rx FIFO */ - rx_words = n_words; - stalled = 10; - while (rx_words) { - if (rx_words == n_words && !(stalled--) && - !(sr & XSPI_SR_TX_EMPTY_MASK) && - (sr & XSPI_SR_RX_EMPTY_MASK)) { - dev_err(&spi->dev, - "Detected stall. Check C_SPI_MODE and C_SPI_MEMORY\n"); - xspi_init_hw(xspi); - return -EIO; - } - - if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) { - xilinx_spi_rx(xspi); - rx_words--; - continue; - } - - sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); - if (!(sr & XSPI_SR_RX_EMPTY_MASK)) { - xilinx_spi_rx(xspi); - rx_words--; - } - } + cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET); + cr |= XSPI_CR_ENABLE; + xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET); + + return 0; +} + +/** + * xspi_unprepare_transfer_hardware - Relaxes hardware after transfer + * @master: Pointer to the spi_master structure which provides + * information about the controller. + * + * This function disables the SPI master controller. + * + * Return: Always 0 + */ +static int xspi_unprepare_transfer_hardware(struct spi_master *master) +{ + struct xilinx_spi *xqspi = spi_master_get_devdata(master); + u32 cr; + + cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET); + cr &= ~XSPI_CR_ENABLE; + xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET); + + pm_runtime_put_sync(xqspi->dev); + + return 0; +} + +/** + * xilinx_spi_runtime_resume - Runtime resume method for the SPI driver + * @dev: Address of the platform_device structure + * + * This function enables the clocks + * + * Return: 0 on success and error value on error + */ +static int __maybe_unused xilinx_spi_runtime_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct xilinx_spi *xspi = spi_master_get_devdata(master); + int ret; - remaining_words -= n_words; + ret = clk_enable(xspi->axi_clk); + if (ret) { + dev_err(dev, "Can not enable AXI clock\n"); + return ret; } - if (use_irq) { - xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET); - xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); + ret = clk_enable(xspi->axi4_clk); + if (ret) { + dev_err(dev, "Can not enable AXI4 clock\n"); + goto clk_disable_axi_clk; } - return t->len; + ret = clk_enable(xspi->spi_clk); + if (ret) { + dev_err(dev, "Can not enable SPI clock\n"); + goto clk_disable_axi4_clk; + } + + return 0; + +clk_disable_axi4_clk: + clk_disable(xspi->axi4_clk); +clk_disable_axi_clk: + clk_disable(xspi->axi_clk); + + return ret; } +/** + * xilinx_spi_runtime_suspend - Runtime suspend method for the SPI driver + * @dev: Address of the platform_device structure + * + * This function disables the clocks + * + * Return: Always 0 + */ +static int __maybe_unused xilinx_spi_runtime_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct xilinx_spi *xspi = spi_master_get_devdata(master); + + clk_disable(xspi->axi_clk); + clk_disable(xspi->axi4_clk); + clk_disable(xspi->spi_clk); + + return 0; +} -/* This driver supports single master mode only. Hence Tx FIFO Empty - * is the only interrupt we care about. - * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode - * Fault are not to happen. +/** + * xilinx_spi_resume - Resume method for the SPI driver + * @dev: Address of the platform_device structure + * + * The function starts the SPI driver queue and initializes the SPI + * controller + * + * Return: 0 on success; error value otherwise */ -static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) +static int __maybe_unused xilinx_spi_resume(struct device *dev) { - struct xilinx_spi *xspi = dev_id; - u32 ipif_isr; + struct spi_master *master = dev_get_drvdata(dev); + struct xilinx_spi *xspi = spi_master_get_devdata(master); + int ret = 0; - /* Get the IPIF interrupts, and clear them immediately */ - ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); - xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET); + if (!pm_runtime_suspended(dev)) { + ret = xilinx_spi_runtime_resume(dev); + if (ret < 0) + return ret; + } - if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ - complete(&xspi->done); - return IRQ_HANDLED; + ret = spi_master_resume(master); + if (ret < 0) { + clk_disable(xspi->axi_clk); + clk_disable(xspi->axi4_clk); + clk_disable(xspi->spi_clk); } - return IRQ_NONE; + return ret; } -static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi) + +/** + * xilinx_spi_suspend - Suspend method for the SPI driver + * @dev: Address of the platform_device structure + * + * This function stops the SPI driver queue and disables the SPI controller + * + * Return: Always 0 + */ +static int __maybe_unused xilinx_spi_suspend(struct device *dev) { - u8 sr; - int n_words = 0; + struct spi_master *master = dev_get_drvdata(dev); + int ret = 0; - /* - * Before the buffer_size detection we reset the core - * to make sure we start with a clean state. - */ - xspi->write_fn(XIPIF_V123B_RESET_MASK, - xspi->regs + XIPIF_V123B_RESETR_OFFSET); + ret = spi_master_suspend(master); + if (ret) + return ret; + + if (!pm_runtime_suspended(dev)) + xilinx_spi_runtime_suspend(dev); - /* Fill the Tx FIFO with as many words as possible */ - do { - xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); - sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); - n_words++; - } while (!(sr & XSPI_SR_TX_FULL_MASK)); + xspi_unprepare_transfer_hardware(master); - return n_words; + return ret; } -static const struct of_device_id xilinx_spi_of_match[] = { - { .compatible = "xlnx,axi-quad-spi-1.00.a", }, - { .compatible = "xlnx,xps-spi-2.00.a", }, - { .compatible = "xlnx,xps-spi-2.00.b", }, - {} +static const struct dev_pm_ops xilinx_spi_dev_pm_ops = { + SET_RUNTIME_PM_OPS(xilinx_spi_runtime_suspend, + xilinx_spi_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(xilinx_spi_suspend, xilinx_spi_resume) }; -MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); +/** + * xilinx_spi_probe - Probe method for the SPI driver + * @pdev: Pointer to the platform_device structure + * + * This function initializes the driver data structures and the hardware. + * + * Return: 0 on success; error value otherwise + */ static int xilinx_spi_probe(struct platform_device *pdev) { struct xilinx_spi *xspi; - struct xspi_platform_data *pdata; struct resource *res; int ret, num_cs = 0, bits_per_word = 8; + u32 cs_num; struct spi_master *master; - u32 tmp; - u8 i; - - pdata = dev_get_platdata(&pdev->dev); - if (pdata) { - num_cs = pdata->num_chipselect; - bits_per_word = pdata->bits_per_word; - } else { - of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits", - &num_cs); - } + struct device_node *nc; + u32 tmp, rx_bus_width, fifo_size; + bool startup_block; - if (!num_cs) { - dev_err(&pdev->dev, - "Missing slave select configuration data\n"); - return -EINVAL; - } + of_property_read_u32(pdev->dev.of_node, "num-cs", + &num_cs); + if (!num_cs) + num_cs = 1; if (num_cs > XILINX_SPI_MAX_CS) { dev_err(&pdev->dev, "Invalid number of spi slaves\n"); return -EINVAL; } + startup_block = of_property_read_bool(pdev->dev.of_node, + "xlnx,startup-block"); + master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi)); if (!master) return -ENODEV; - /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | - SPI_CS_HIGH; - xspi = spi_master_get_devdata(master); - xspi->cs_inactive = 0xffffffff; - xspi->bitbang.master = master; - xspi->bitbang.chipselect = xilinx_spi_chipselect; - xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; - xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; - init_completion(&xspi->done); - + master->dev.of_node = pdev->dev.of_node; + platform_set_drvdata(pdev, master); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); xspi->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(xspi->regs)) { @@ -439,20 +715,104 @@ static int xilinx_spi_probe(struct platform_device *pdev) goto put_master; } - master->bus_num = pdev->id; - master->num_chipselect = num_cs; - master->dev.of_node = pdev->dev.of_node; + ret = of_property_read_u32(pdev->dev.of_node, "fifo-size", + &fifo_size); + if (ret < 0) { + dev_err(&pdev->dev, + "Missing fifo size\n"); + return -EINVAL; + } + of_property_read_u32(pdev->dev.of_node, "bits-per-word", + &bits_per_word); + + xspi->rx_bus_width = XSPI_ONE_BITS_PER_WORD; + for_each_available_child_of_node(pdev->dev.of_node, nc) { + if (startup_block) { + ret = of_property_read_u32(nc, "reg", + &cs_num); + if (ret < 0) + return -EINVAL; + } + ret = of_property_read_u32(nc, "spi-rx-bus-width", + &rx_bus_width); + if (!ret) { + xspi->rx_bus_width = rx_bus_width; + break; + } + } + + xspi->axi_clk = devm_clk_get(&pdev->dev, "axi_clk"); + if (IS_ERR(xspi->axi_clk)) { + if (PTR_ERR(xspi->axi_clk) != -ENOENT) { + ret = PTR_ERR(xspi->axi_clk); + goto put_master; + } + + /* + * Clock framework support is optional, continue on, + * anyways if we don't find a matching clock + */ + xspi->axi_clk = NULL; + } + + ret = clk_prepare(xspi->axi_clk); + if (ret) { + dev_err(&pdev->dev, "Failed to prepare AXI clock\n"); + goto put_master; + } + + xspi->axi4_clk = devm_clk_get(&pdev->dev, "axi4_clk"); + if (IS_ERR(xspi->axi4_clk)) { + if (PTR_ERR(xspi->axi4_clk) != -ENOENT) { + ret = PTR_ERR(xspi->axi4_clk); + goto clk_unprepare_axi_clk; + } + + /* + * Clock framework support is optional, continue on, + * anyways if we don't find a matching clock + */ + xspi->axi4_clk = NULL; + } + + ret = clk_prepare(xspi->axi4_clk); + if (ret) { + dev_err(&pdev->dev, "Failed to prepare AXI4 clock\n"); + goto clk_unprepare_axi_clk; + } + + xspi->spi_clk = devm_clk_get(&pdev->dev, "spi_clk"); + if (IS_ERR(xspi->spi_clk)) { + if (PTR_ERR(xspi->spi_clk) != -ENOENT) { + ret = PTR_ERR(xspi->spi_clk); + goto clk_unprepare_axi4_clk; + } + + /* + * Clock framework support is optional, continue on, + * anyways if we don't find a matching clock + */ + xspi->spi_clk = NULL; + } + + ret = clk_prepare(xspi->spi_clk); + if (ret) { + dev_err(&pdev->dev, "Failed to prepare SPI clock\n"); + goto clk_unprepare_axi4_clk; + } + + pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + goto clk_unprepare_all; + + xspi->dev = &pdev->dev; - /* - * Detect endianess on the IP via loop bit in CR. Detection - * must be done before reset is sent because incorrect reset - * value generates error interrupt. - * Setup little endian helper functions first and try to use them - * and check if bit was correctly setup or not. - */ xspi->read_fn = xspi_read32; xspi->write_fn = xspi_write32; - + /* Detect endianness on the IP via loop bit in CR register*/ xspi->write_fn(XSPI_CR_LOOP, xspi->regs + XSPI_CR_OFFSET); tmp = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); tmp &= XSPI_CR_LOOP; @@ -461,62 +821,112 @@ static int xilinx_spi_probe(struct platform_device *pdev) xspi->write_fn = xspi_write32_be; } - master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word); - xspi->bytes_per_word = bits_per_word / 8; - xspi->buffer_size = xilinx_spi_find_buffer_size(xspi); - + xspi->buffer_size = fifo_size; xspi->irq = platform_get_irq(pdev, 0); if (xspi->irq < 0 && xspi->irq != -ENXIO) { ret = xspi->irq; - goto put_master; + goto clk_unprepare_all; } else if (xspi->irq >= 0) { /* Register for SPI Interrupt */ - ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0, - dev_name(&pdev->dev), xspi); + ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, + 0, dev_name(&pdev->dev), master); if (ret) - goto put_master; + goto clk_unprepare_all; } /* SPI controller initializations */ xspi_init_hw(xspi); - ret = spi_bitbang_start(&xspi->bitbang); - if (ret) { - dev_err(&pdev->dev, "spi_bitbang_start FAILED\n"); - goto put_master; + pm_runtime_put(&pdev->dev); + + master->bus_num = pdev->id; + master->num_chipselect = num_cs; + master->setup = xspi_setup; + master->set_cs = xspi_chipselect; + master->transfer_one = xspi_start_transfer; + master->prepare_transfer_hardware = xspi_prepare_transfer_hardware; + master->unprepare_transfer_hardware = xspi_unprepare_transfer_hardware; + master->bits_per_word_mask = SPI_BPW_MASK(8); + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + + xspi->bytes_per_word = bits_per_word / 8; + xspi->tx_fifo = xspi_fill_tx_fifo_8; + xspi->rx_fifo = xspi_read_rx_fifo_8; + if (xspi->rx_bus_width == XSPI_RX_ONE_WIRE) { + if (xspi->bytes_per_word == XSPI_TWO_BITS_PER_WORD) { + xspi->tx_fifo = xspi_fill_tx_fifo_16; + xspi->rx_fifo = xspi_read_rx_fifo_16; + } else if (xspi->bytes_per_word == XSPI_FOUR_BITS_PER_WORD) { + xspi->tx_fifo = xspi_fill_tx_fifo_32; + xspi->rx_fifo = xspi_read_rx_fifo_32; + } + } else if (xspi->rx_bus_width == XSPI_RX_FOUR_WIRE) { + master->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD; + } else { + dev_err(&pdev->dev, "Dual Mode not supported\n"); + goto clk_unprepare_all; } + xspi->cs_inactive = 0xffffffff; - dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", - (unsigned long long)res->start, xspi->regs, xspi->irq); + /* + * This is the work around for the startup block issue in + * the spi controller. SPI clock is passing through STARTUP + * block to FLASH. STARTUP block don't provide clock as soon + * as QSPI provides command. So first command fails. + */ + if (startup_block) + xilinx_spi_startup_block(xspi, cs_num); - if (pdata) { - for (i = 0; i < pdata->num_devices; i++) - spi_new_device(master, pdata->devices + i); + ret = spi_register_master(master); + if (ret) { + dev_err(&pdev->dev, "spi_register_master failed\n"); + goto clk_unprepare_all; } - platform_set_drvdata(pdev, master); - return 0; + return ret; +clk_unprepare_all: + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + clk_unprepare(xspi->spi_clk); +clk_unprepare_axi4_clk: + clk_unprepare(xspi->axi4_clk); +clk_unprepare_axi_clk: + clk_unprepare(xspi->axi_clk); put_master: spi_master_put(master); return ret; } +/** + * xilinx_spi_remove - Remove method for the SPI 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 Always + */ static int xilinx_spi_remove(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); struct xilinx_spi *xspi = spi_master_get_devdata(master); void __iomem *regs_base = xspi->regs; - spi_bitbang_stop(&xspi->bitbang); - /* Disable all the interrupts just in case */ xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); /* Disable the global IPIF interrupt */ xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); - spi_master_put(xspi->bitbang.master); + pm_runtime_disable(&pdev->dev); + + clk_disable_unprepare(xspi->axi_clk); + clk_disable_unprepare(xspi->axi4_clk); + clk_disable_unprepare(xspi->spi_clk); + + spi_unregister_master(master); return 0; } @@ -524,12 +934,21 @@ static int xilinx_spi_remove(struct platform_device *pdev) /* work with hotplug and coldplug */ MODULE_ALIAS("platform:" XILINX_SPI_NAME); +static const struct of_device_id xilinx_spi_of_match[] = { + { .compatible = "xlnx,axi-quad-spi-1.00.a", }, + { .compatible = "xlnx,xps-spi-2.00.a", }, + { .compatible = "xlnx,xps-spi-2.00.b", }, + {} +}; +MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); + static struct platform_driver xilinx_spi_driver = { .probe = xilinx_spi_probe, .remove = xilinx_spi_remove, .driver = { .name = XILINX_SPI_NAME, .of_match_table = xilinx_spi_of_match, + .pm = &xilinx_spi_dev_pm_ops, }, }; module_platform_driver(xilinx_spi_driver); diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index c6bee67decb5..2041d5dcf294 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -129,6 +129,9 @@ * @rxbuf: Pointer to the RX buffer * @tx_bytes: Number of bytes left to transfer * @rx_bytes: Number of bytes left to receive + * @is_dual: Flag to indicate whether dual flash memories are used + * @is_instr: Flag to indicate if transfer contains an instruction + * (Used in dual parallel configuration) * @data_completion: completion structure */ struct zynq_qspi { @@ -141,6 +144,8 @@ struct zynq_qspi { u8 *rxbuf; int tx_bytes; int rx_bytes; + u32 is_dual; + u8 is_instr; struct completion data_completion; }; @@ -213,6 +218,14 @@ static void zynq_qspi_init_hw(struct zynq_qspi *xqspi) zynq_qspi_write(xqspi, ZYNQ_QSPI_TX_THRESH_OFFSET, ZYNQ_QSPI_TX_THRESHOLD); + if (xqspi->is_dual) + /* Enable two memories on separate buses */ + zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, + (ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + ZYNQ_QSPI_LCFG_SEP_BUS_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FAST_READ_QOUT_CODE)); + zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, ZYNQ_QSPI_ENABLE_ENABLE_MASK); } @@ -236,15 +249,23 @@ static bool zynq_qspi_supports_op(struct spi_mem *mem, * 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) + * + * Note: In case of dual parallel connection, even number of bytes are read + * when odd bytes are requested to avoid transfer of a nibble to each flash. + * The receive buffer though, is populated with the number of bytes requested. */ static void zynq_qspi_rxfifo_op(struct zynq_qspi *xqspi, unsigned int size) { + unsigned int xsize; u32 data; data = zynq_qspi_read(xqspi, ZYNQ_QSPI_RXD_OFFSET); if (xqspi->rxbuf) { - memcpy(xqspi->rxbuf, ((u8 *)&data) + 4 - size, size); + xsize = size; + if (xqspi->is_dual && !xqspi->is_instr && (size % 2)) + xsize++; + memcpy(xqspi->rxbuf, ((u8 *)&data) + 4 - xsize, size); xqspi->rxbuf += size; } @@ -257,12 +278,19 @@ static void zynq_qspi_rxfifo_op(struct zynq_qspi *xqspi, unsigned int size) * zynq_qspi_txfifo_op - Write 1..4 bytes from TX buffer to TxFIFO * @xqspi: Pointer to the zynq_qspi structure * @size: Number of bytes to be written (1..4) + * + * In dual parallel configuration, when read/write data operations + * are performed, odd data bytes have to be converted to even to + * avoid a nibble (of data when programming / dummy when reading) + * going to individual flash devices, where a byte is expected. + * This check is only for data and will not apply for commands. */ static void zynq_qspi_txfifo_op(struct zynq_qspi *xqspi, unsigned int size) { static const unsigned int offset[4] = { ZYNQ_QSPI_TXD_00_01_OFFSET, ZYNQ_QSPI_TXD_00_10_OFFSET, ZYNQ_QSPI_TXD_00_11_OFFSET, ZYNQ_QSPI_TXD_00_00_OFFSET }; + unsigned int xsize; u32 data; if (xqspi->txbuf) { @@ -274,7 +302,11 @@ static void zynq_qspi_txfifo_op(struct zynq_qspi *xqspi, unsigned int size) } xqspi->tx_bytes -= size; - zynq_qspi_write(xqspi, offset[size - 1], data); + + xsize = size; + if (xqspi->is_dual && !xqspi->is_instr && (size % 2)) + xsize++; + zynq_qspi_write(xqspi, offset[xsize - 1], data); } /** @@ -295,6 +327,7 @@ static void zynq_qspi_chipselect(struct spi_device *spi, bool assert) config_reg |= (((~(BIT(spi->chip_select))) << ZYNQ_QSPI_SS_SHIFT) & ZYNQ_QSPI_CONFIG_SSCTRL_MASK); + xqspi->is_instr = 1; } else { config_reg |= ZYNQ_QSPI_CONFIG_SSCTRL_MASK; } @@ -637,6 +670,12 @@ static int zynq_qspi_probe(struct platform_device *pdev) goto remove_master; } + if (of_property_read_u32(pdev->dev.of_node, "is-dual", + &xqspi->is_dual)) { + dev_warn(&pdev->dev, "couldn't determine configuration info"); + dev_warn(&pdev->dev, "about dual memories. defaulting to single memory\n"); + } + xqspi->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(xqspi->pclk)) { dev_err(&pdev->dev, "pclk clock not found.\n"); diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index ddf408a6b60c..2b794f57964d 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/of_irq.h> #include <linux/of_address.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> @@ -33,6 +34,7 @@ #define GQSPI_RXD_OFST 0x00000120 #define GQSPI_TX_THRESHOLD_OFST 0x00000128 #define GQSPI_RX_THRESHOLD_OFST 0x0000012C +#define IOU_TAPDLY_BYPASS_OFST 0x0000003C #define GQSPI_LPBK_DLY_ADJ_OFST 0x00000138 #define GQSPI_GEN_FIFO_OFST 0x00000140 #define GQSPI_SEL_OFST 0x00000144 @@ -47,6 +49,7 @@ #define GQSPI_QSPIDMA_DST_I_MASK_OFST 0x00000820 #define GQSPI_QSPIDMA_DST_ADDR_OFST 0x00000800 #define GQSPI_QSPIDMA_DST_ADDR_MSB_OFST 0x00000828 +#define GQSPI_DATA_DLY_ADJ_OFST 0x000001F8 /* GQSPI register bit masks */ #define GQSPI_SEL_MASK 0x00000001 @@ -132,12 +135,44 @@ #define GQSPI_SELECT_MODE_QUADSPI 0x4 #define GQSPI_DMA_UNALIGN 0x3 #define GQSPI_DEFAULT_NUM_CS 1 /* Default number of chip selects */ +#define GQSPI_RX_BUS_WIDTH_QUAD 0x4 +#define GQSPI_RX_BUS_WIDTH_DUAL 0x2 +#define GQSPI_RX_BUS_WIDTH_SINGLE 0x1 +#define GQSPI_TX_BUS_WIDTH_QUAD 0x4 +#define GQSPI_TX_BUS_WIDTH_DUAL 0x2 +#define GQSPI_TX_BUS_WIDTH_SINGLE 0x1 +#define GQSPI_LPBK_DLY_ADJ_LPBK_SHIFT 5 +#define GQSPI_LPBK_DLY_ADJ_DLY_1 0x2 +#define GQSPI_LPBK_DLY_ADJ_DLY_1_SHIFT 3 +#define GQSPI_LPBK_DLY_ADJ_DLY_0 0x3 +#define GQSPI_USE_DATA_DLY 0x1 +#define GQSPI_USE_DATA_DLY_SHIFT 31 +#define GQSPI_DATA_DLY_ADJ_VALUE 0x2 +#define GQSPI_DATA_DLY_ADJ_SHIFT 28 +#define TAP_DLY_BYPASS_LQSPI_RX_VALUE 0x1 +#define TAP_DLY_BYPASS_LQSPI_RX_SHIFT 2 + +/* set to differentiate versal from zynqmp, 1=versal, 0=zynqmp */ +#define QSPI_QUIRK_HAS_TAPDELAY BIT(0) + +#define GQSPI_FREQ_40MHZ 40000000 +#define GQSPI_FREQ_100MHZ 100000000 +#define GQSPI_FREQ_150MHZ 150000000 +#define IOU_TAPDLY_BYPASS_MASK 0x7 #define SPI_AUTOSUSPEND_TIMEOUT 3000 enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA}; static const struct zynqmp_eemi_ops *eemi_ops; /** + * struct zynq_platform_data - zynqmp qspi platform data structure + * @quirks: Flags is used to identify the platform + */ +struct qspi_platform_data { + u32 quirks; +}; + +/** * struct zynqmp_qspi - Defines qspi driver instance * @regs: Virtual address of the QSPI controller registers * @refclk: Pointer to the peripheral clock @@ -152,8 +187,14 @@ static const struct zynqmp_eemi_ops *eemi_ops; * @genfifobus: Used to select the upper or lower bus * @dma_rx_bytes: Remaining bytes to receive by DMA mode * @dma_addr: DMA address after mapping the kernel buffer + * @tx_bus_width: Used to represent number of data wires for tx + * @rx_bus_width: Used to represent number of data wires * @genfifoentry: Used for storing the genfifoentry instruction. + * @isinstr: To determine whether the transfer is instruction * @mode: Defines the mode in which QSPI is operating + * @speed_hz: Current SPI bus clock speed in hz + * @io_mode: Defines the operating mode, either IO or dma + * @has_tapdelay: Used for tapdelay register available in qspi */ struct zynqmp_qspi { void __iomem *regs; @@ -169,14 +210,22 @@ struct zynqmp_qspi { u32 genfifobus; u32 dma_rx_bytes; dma_addr_t dma_addr; + u32 rx_bus_width; + u32 tx_bus_width; u32 genfifoentry; + bool isinstr; enum mode_type mode; + u32 speed_hz; + bool io_mode; + bool has_tapdelay; }; /** - * zynqmp_gqspi_read: For GQSPI controller read operation + * zynqmp_gqspi_read - For GQSPI controller read operation * @xqspi: Pointer to the zynqmp_qspi structure * @offset: Offset from where to read + * + * Return: Value read from the qspi register */ static u32 zynqmp_gqspi_read(struct zynqmp_qspi *xqspi, u32 offset) { @@ -184,7 +233,7 @@ static u32 zynqmp_gqspi_read(struct zynqmp_qspi *xqspi, u32 offset) } /** - * zynqmp_gqspi_write: For GQSPI controller write operation + * zynqmp_gqspi_write - For GQSPI controller write operation * @xqspi: Pointer to the zynqmp_qspi structure * @offset: Offset where to write * @val: Value to be written @@ -196,10 +245,10 @@ static inline void zynqmp_gqspi_write(struct zynqmp_qspi *xqspi, u32 offset, } /** - * zynqmp_gqspi_selectslave: For selection of slave device + * zynqmp_gqspi_selectslave - For selection of slave device * @instanceptr: Pointer to the zynqmp_qspi structure - * @flashcs: For chip select - * @flashbus: To check which bus is selected- upper or lower + * @slavecs: For chip select + * @slavebus: To check which bus is selected- upper or lower */ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr, u8 slavecs, u8 slavebus) @@ -243,7 +292,76 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr, } /** - * zynqmp_qspi_init_hw: Initialize the hardware + * zynqmp_qspi_set_tapdelay - To configure qspi tap delays + * @xqspi: Pointer to the zynqmp_qspi structure + * @baudrateval: Buadrate to configure + */ +static void zynqmp_qspi_set_tapdelay(struct zynqmp_qspi *xqspi, u32 baudrateval) +{ + u32 tapdlybypass = 0, lpbkdlyadj = 0, datadlyadj = 0, clk_rate; + u32 reqhz = 0; + + if (!eemi_ops->ioctl) + return; + + clk_rate = clk_get_rate(xqspi->refclk); + reqhz = (clk_rate / (GQSPI_BAUD_DIV_SHIFT << baudrateval)); + + if (!xqspi->has_tapdelay) { + if (reqhz <= GQSPI_FREQ_40MHZ) { + eemi_ops->ioctl(NODE_QSPI, IOCTL_SET_TAPDELAY_BYPASS, + PM_TAPDELAY_QSPI, + PM_TAPDELAY_BYPASS_ENABLE, + NULL); + } else if (reqhz <= GQSPI_FREQ_100MHZ) { + eemi_ops->ioctl(NODE_QSPI, IOCTL_SET_TAPDELAY_BYPASS, + PM_TAPDELAY_QSPI, + PM_TAPDELAY_BYPASS_ENABLE, + NULL); + lpbkdlyadj |= (GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK); + datadlyadj |= ((GQSPI_USE_DATA_DLY << + GQSPI_USE_DATA_DLY_SHIFT) + | (GQSPI_DATA_DLY_ADJ_VALUE << + GQSPI_DATA_DLY_ADJ_SHIFT)); + } else if (reqhz <= GQSPI_FREQ_150MHZ) { + lpbkdlyadj |= GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK; + } + } else { + if (reqhz <= GQSPI_FREQ_40MHZ) { + tapdlybypass |= (TAP_DLY_BYPASS_LQSPI_RX_VALUE << + TAP_DLY_BYPASS_LQSPI_RX_SHIFT); + } else if (reqhz <= GQSPI_FREQ_100MHZ) { + tapdlybypass |= (TAP_DLY_BYPASS_LQSPI_RX_VALUE << + TAP_DLY_BYPASS_LQSPI_RX_SHIFT); + lpbkdlyadj |= (GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK); + datadlyadj |= ((GQSPI_USE_DATA_DLY << + GQSPI_USE_DATA_DLY_SHIFT) + | (GQSPI_DATA_DLY_ADJ_VALUE << + GQSPI_DATA_DLY_ADJ_SHIFT)); + } else if (reqhz <= GQSPI_FREQ_150MHZ) { + lpbkdlyadj |= GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK; + } + zynqmp_gqspi_write(xqspi, + IOU_TAPDLY_BYPASS_OFST, tapdlybypass); + } + + zynqmp_gqspi_write(xqspi, GQSPI_LPBK_DLY_ADJ_OFST, lpbkdlyadj); + zynqmp_gqspi_write(xqspi, GQSPI_DATA_DLY_ADJ_OFST, datadlyadj); +} + +static u32 zynqmp_disable_intr(struct zynqmp_qspi *xqspi) +{ + u32 value; + + zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK); + value = zynqmp_gqspi_read(xqspi, GQSPI_IMASK_OFST); + zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK); + + return value; +} + +/** + * zynqmp_qspi_init_hw - Initialize the hardware * @xqspi: Pointer to the zynqmp_qspi structure * * The default settings of the QSPI controller's configurable parameters on @@ -267,9 +385,7 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi) /* Select the GQSPI mode */ zynqmp_gqspi_write(xqspi, GQSPI_SEL_OFST, GQSPI_SEL_MASK); /* Clear and disable interrupts */ - zynqmp_gqspi_write(xqspi, GQSPI_ISR_OFST, - zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST) | - GQSPI_ISR_WR_TO_CLR_MASK); + zynqmp_disable_intr(xqspi); /* Clear the DMA STS */ zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_I_STS_OFST, zynqmp_gqspi_read(xqspi, @@ -321,17 +437,18 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi) zynqmp_gqspi_selectslave(xqspi, GQSPI_SELECT_FLASH_CS_LOWER, GQSPI_SELECT_FLASH_BUS_LOWER); - /* Initialize DMA */ - zynqmp_gqspi_write(xqspi, + if (!xqspi->io_mode) { + /* Initialize DMA */ + zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_CTRL_OFST, GQSPI_QSPIDMA_DST_CTRL_RESET_VAL); - + } /* Enable the GQSPI */ zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK); } /** - * zynqmp_qspi_copy_read_data: Copy data to RX buffer + * zynqmp_qspi_copy_read_data - Copy data to RX buffer * @xqspi: Pointer to the zynqmp_qspi structure * @data: The variable where data is stored * @size: Number of bytes to be copied from data to RX buffer @@ -345,7 +462,7 @@ static void zynqmp_qspi_copy_read_data(struct zynqmp_qspi *xqspi, } /** - * zynqmp_prepare_transfer_hardware: Prepares hardware for transfer. + * zynqmp_prepare_transfer_hardware - Prepares hardware for transfer. * @master: Pointer to the spi_master structure which provides * information about the controller. * @@ -362,7 +479,7 @@ static int zynqmp_prepare_transfer_hardware(struct spi_master *master) } /** - * zynqmp_unprepare_transfer_hardware: Relaxes hardware after transfer + * zynqmp_unprepare_transfer_hardware - Relaxes hardware after transfer * @master: Pointer to the spi_master structure which provides * information about the controller. * @@ -379,7 +496,7 @@ static int zynqmp_unprepare_transfer_hardware(struct spi_master *master) } /** - * zynqmp_qspi_chipselect: Select or deselect the chip select line + * zynqmp_qspi_chipselect - Select or deselect the chip select line * @qspi: Pointer to the spi_device structure * @is_high: Select(0) or deselect (1) the chip select line */ @@ -390,11 +507,27 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high) u32 genfifoentry = 0x0, statusreg; genfifoentry |= GQSPI_GENFIFO_MODE_SPI; + + if (qspi->master->flags & SPI_MASTER_BOTH_CS) { + zynqmp_gqspi_selectslave(xqspi, + GQSPI_SELECT_FLASH_CS_BOTH, + GQSPI_SELECT_FLASH_BUS_BOTH); + } else if (qspi->master->flags & SPI_MASTER_U_PAGE) { + zynqmp_gqspi_selectslave(xqspi, + GQSPI_SELECT_FLASH_CS_UPPER, + GQSPI_SELECT_FLASH_BUS_LOWER); + } else { + zynqmp_gqspi_selectslave(xqspi, + GQSPI_SELECT_FLASH_CS_LOWER, + GQSPI_SELECT_FLASH_BUS_LOWER); + } + genfifoentry |= xqspi->genfifobus; if (!is_high) { genfifoentry |= xqspi->genfifocs; genfifoentry |= GQSPI_GENFIFO_CS_SETUP; + xqspi->isinstr = true; } else { genfifoentry |= GQSPI_GENFIFO_CS_HOLD; } @@ -415,8 +548,7 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high) if ((statusreg & GQSPI_ISR_GENFIFOEMPTY_MASK) && (statusreg & GQSPI_ISR_TXEMPTY_MASK)) break; - else - cpu_relax(); + cpu_relax(); } while (!time_after_eq(jiffies, timeout)); if (time_after_eq(jiffies, timeout)) @@ -424,7 +556,7 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high) } /** - * zynqmp_qspi_setup_transfer: Configure QSPI controller for specified + * zynqmp_qspi_setup_transfer - Configure QSPI controller for specified * transfer * @qspi: Pointer to the spi_device structure * @transfer: Pointer to the spi_transfer structure which provides @@ -457,33 +589,39 @@ static int zynqmp_qspi_setup_transfer(struct spi_device *qspi, else req_hz = qspi->max_speed_hz; - /* Set the clock frequency */ - /* If req_hz == 0, default to lowest speed */ - clk_rate = clk_get_rate(xqspi->refclk); + if (xqspi->speed_hz != req_hz) { + /* Set the clock frequency */ + /* If req_hz == 0, default to lowest speed */ + clk_rate = clk_get_rate(xqspi->refclk); - while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) && - (clk_rate / - (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > req_hz) - baud_rate_val++; + while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) && + (clk_rate / + (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > req_hz) + baud_rate_val++; - config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST); + config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST); - /* Set the QSPI clock phase and clock polarity */ - config_reg &= (~GQSPI_CFG_CLK_PHA_MASK) & (~GQSPI_CFG_CLK_POL_MASK); + /* Set the QSPI clock phase and clock polarity */ + config_reg &= (~GQSPI_CFG_CLK_PHA_MASK) & + (~GQSPI_CFG_CLK_POL_MASK); - if (qspi->mode & SPI_CPHA) - config_reg |= GQSPI_CFG_CLK_PHA_MASK; - if (qspi->mode & SPI_CPOL) - config_reg |= GQSPI_CFG_CLK_POL_MASK; + if (qspi->mode & SPI_CPHA) + config_reg |= GQSPI_CFG_CLK_PHA_MASK; + if (qspi->mode & SPI_CPOL) + config_reg |= GQSPI_CFG_CLK_POL_MASK; + config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK; + config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT); + zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg); + xqspi->speed_hz = clk_rate / (GQSPI_BAUD_DIV_SHIFT << + baud_rate_val); + zynqmp_qspi_set_tapdelay(xqspi, baud_rate_val); + } - config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK; - config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT); - zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg); return 0; } /** - * zynqmp_qspi_setup: Configure the QSPI controller + * zynqmp_qspi_setup - Configure the QSPI controller * @qspi: Pointer to the spi_device structure * * Sets the operational mode of QSPI controller for the next QSPI transfer, @@ -499,7 +637,7 @@ static int zynqmp_qspi_setup(struct spi_device *qspi) } /** - * zynqmp_qspi_filltxfifo: Fills the TX FIFO as long as there is room in + * zynqmp_qspi_filltxfifo - Fills the TX FIFO as long as there is room in * the FIFO or the bytes required to be * transmitted. * @xqspi: Pointer to the zynqmp_qspi structure @@ -525,7 +663,7 @@ static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi *xqspi, int size) } /** - * zynqmp_qspi_readrxfifo: Fills the RX FIFO as long as there is room in + * zynqmp_qspi_readrxfifo - Fills the RX FIFO as long as there is room in * the FIFO. * @xqspi: Pointer to the zynqmp_qspi structure * @size: Number of bytes to be copied from RX buffer to RX FIFO @@ -538,7 +676,7 @@ static void zynqmp_qspi_readrxfifo(struct zynqmp_qspi *xqspi, u32 size) while ((count < size) && (xqspi->bytes_to_receive > 0)) { if (xqspi->bytes_to_receive >= 4) { (*(u32 *) xqspi->rxbuf) = - zynqmp_gqspi_read(xqspi, GQSPI_RXD_OFST); + zynqmp_gqspi_read(xqspi, GQSPI_RXD_OFST); xqspi->rxbuf += 4; xqspi->bytes_to_receive -= 4; count += 4; @@ -553,7 +691,40 @@ static void zynqmp_qspi_readrxfifo(struct zynqmp_qspi *xqspi, u32 size) } /** - * zynqmp_process_dma_irq: Handler for DMA done interrupt of QSPI + * zynqmp_qspi_preparedummy - Prepares the dummy entry + * + * @xqspi: Pointer to the zynqmp_qspi structure + * @transfer: It is a pointer to the structure containing transfer data. + * @genfifoentry: genfifoentry is pointer to the variable in which + * GENFIFO mask is returned to calling function + */ +static void zynqmp_qspi_preparedummy(struct zynqmp_qspi *xqspi, + struct spi_transfer *transfer, + u32 *genfifoentry) +{ + /* For dummy Tx and Rx are NULL */ + *genfifoentry &= ~(GQSPI_GENFIFO_TX | GQSPI_GENFIFO_RX); + + /* SPI mode */ + *genfifoentry &= ~GQSPI_GENFIFO_MODE_QUADSPI; + if (xqspi->rx_bus_width == GQSPI_RX_BUS_WIDTH_QUAD || + xqspi->tx_bus_width == GQSPI_TX_BUS_WIDTH_QUAD) + *genfifoentry |= GQSPI_GENFIFO_MODE_QUADSPI; + else if (xqspi->rx_bus_width == GQSPI_RX_BUS_WIDTH_DUAL || + xqspi->tx_bus_width == GQSPI_TX_BUS_WIDTH_DUAL) + *genfifoentry |= GQSPI_GENFIFO_MODE_DUALSPI; + else + *genfifoentry |= GQSPI_GENFIFO_MODE_SPI; + + /* Immediate data */ + *genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK; + + if (transfer->dummy) + *genfifoentry |= transfer->dummy; +} + +/** + * zynqmp_process_dma_irq - Handler for DMA done interrupt of QSPI * controller * @xqspi: zynqmp_qspi instance pointer * @@ -601,7 +772,7 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi) } /** - * zynqmp_qspi_irq: Interrupt service routine of the QSPI controller + * zynqmp_qspi_irq - Interrupt service routine of the QSPI controller * @irq: IRQ number * @dev_id: Pointer to the xqspi structure * @@ -639,23 +810,29 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id) if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK) { zynqmp_process_dma_irq(xqspi); ret = IRQ_HANDLED; - } else if (!(mask & GQSPI_IER_RXEMPTY_MASK) && - (mask & GQSPI_IER_GENFIFOEMPTY_MASK)) { + } else if ((mask & GQSPI_IER_RXNEMPTY_MASK)) { + zynqmp_qspi_readrxfifo(xqspi, GQSPI_RX_FIFO_FILL); + ret = IRQ_HANDLED; + } + if (!(mask & GQSPI_IER_RXEMPTY_MASK) && + (mask & GQSPI_IER_GENFIFOEMPTY_MASK)) { zynqmp_qspi_readrxfifo(xqspi, GQSPI_RX_FIFO_FILL); ret = IRQ_HANDLED; } if ((xqspi->bytes_to_receive == 0) && (xqspi->bytes_to_transfer == 0) && ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) { - zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK); + zynqmp_disable_intr(xqspi); + xqspi->isinstr = false; spi_finalize_current_transfer(master); ret = IRQ_HANDLED; } + return ret; } /** - * zynqmp_qspi_selectspimode: Selects SPI mode - x1 or x2 or x4. + * zynqmp_qspi_selectspimode - Selects SPI mode - x1 or x2 or x4. * @xqspi: xqspi is a pointer to the GQSPI instance * @spimode: spimode - SPI or DUAL or QUAD. * Return: Mask to set desired SPI mode in GENFIFO entry. @@ -683,7 +860,7 @@ static inline u32 zynqmp_qspi_selectspimode(struct zynqmp_qspi *xqspi, } /** - * zynq_qspi_setuprxdma: This function sets up the RX DMA operation + * zynq_qspi_setuprxdma - This function sets up the RX DMA operation * @xqspi: xqspi is a pointer to the GQSPI instance. */ static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi) @@ -692,8 +869,9 @@ static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi) dma_addr_t addr; u64 dma_align = (u64)(uintptr_t)xqspi->rxbuf; - if ((xqspi->bytes_to_receive < 8) || - ((dma_align & GQSPI_DMA_UNALIGN) != 0x0)) { + if (((xqspi->bytes_to_receive < 8) || (xqspi->io_mode)) || + ((dma_align & GQSPI_DMA_UNALIGN) != 0x0) || + is_vmalloc_addr(xqspi->rxbuf)) { /* Setting to IO mode */ config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST); config_reg &= ~GQSPI_CFG_MODE_EN_MASK; @@ -708,8 +886,10 @@ static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi) addr = dma_map_single(xqspi->dev, (void *)xqspi->rxbuf, rx_bytes, DMA_FROM_DEVICE); - if (dma_mapping_error(xqspi->dev, addr)) + if (dma_mapping_error(xqspi->dev, addr)) { dev_err(xqspi->dev, "ERR:rxdma:memory not mapped\n"); + return; + } xqspi->dma_rx_bytes = rx_bytes; xqspi->dma_addr = addr; @@ -733,7 +913,7 @@ static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi) } /** - * zynqmp_qspi_txrxsetup: This function checks the TX/RX buffers in + * zynqmp_qspi_txrxsetup - This function checks the TX/RX buffers in * the transfer and sets up the GENFIFO entries, * TX FIFO as required. * @xqspi: xqspi is a pointer to the GQSPI instance. @@ -755,7 +935,7 @@ static void zynqmp_qspi_txrxsetup(struct zynqmp_qspi *xqspi, *genfifoentry |= GQSPI_GENFIFO_TX; *genfifoentry |= zynqmp_qspi_selectspimode(xqspi, transfer->tx_nbits); - xqspi->bytes_to_transfer = transfer->len; + xqspi->bytes_to_transfer = transfer->len - (transfer->dummy/8); if (xqspi->mode == GQSPI_MODE_DMA) { config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST); @@ -784,7 +964,7 @@ static void zynqmp_qspi_txrxsetup(struct zynqmp_qspi *xqspi, } /** - * zynqmp_qspi_start_transfer: Initiates the QSPI transfer + * zynqmp_qspi_start_transfer - Initiates the QSPI transfer * @master: Pointer to the spi_master structure which provides * information about the controller. * @qspi: Pointer to the spi_device structure @@ -811,18 +991,28 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master, genfifoentry |= xqspi->genfifocs; genfifoentry |= xqspi->genfifobus; + if (!xqspi->isinstr && (master->flags & SPI_MASTER_DATA_STRIPE)) { + if (transfer->stripe) + genfifoentry |= GQSPI_GENFIFO_STRIPE; + } zynqmp_qspi_txrxsetup(xqspi, transfer, &genfifoentry); if (xqspi->mode == GQSPI_MODE_DMA) transfer_len = xqspi->dma_rx_bytes; else - transfer_len = transfer->len; + transfer_len = transfer->len - (transfer->dummy/8); xqspi->genfifoentry = genfifoentry; if ((transfer_len) < GQSPI_GENFIFO_IMM_DATA_MASK) { genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK; genfifoentry |= transfer_len; zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry); + if (transfer->dummy || transfer->tx_nbits >= 1) { + zynqmp_qspi_preparedummy(xqspi, transfer, + &genfifoentry); + zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, + genfifoentry); + } } else { int tempcount = transfer_len; u32 exponent = 8; /* 2^8 = 256 */ @@ -849,6 +1039,12 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master, if (imm_data != 0) { genfifoentry &= ~GQSPI_GENFIFO_EXP; genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK; + if (imm_data % 4 != 0) { + if (((imm_data + 4 - (imm_data % 4)) & 0xFF) == 0x00) + imm_data = 0xFF; + else + imm_data = imm_data + 4 - (imm_data % 4); + } genfifoentry |= (u8) (imm_data & 0xFF); zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry); @@ -869,7 +1065,6 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master, if (xqspi->txbuf != NULL) /* Enable interrupts for TX */ zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST, - GQSPI_IER_TXEMPTY_MASK | GQSPI_IER_GENFIFOEMPTY_MASK | GQSPI_IER_TXNOT_FULL_MASK); @@ -883,8 +1078,7 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master, } else { zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST, GQSPI_IER_GENFIFOEMPTY_MASK | - GQSPI_IER_RXNEMPTY_MASK | - GQSPI_IER_RXEMPTY_MASK); + GQSPI_IER_RXNEMPTY_MASK); } } @@ -892,8 +1086,8 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master, } /** - * zynqmp_qspi_suspend: Suspend method for the QSPI driver - * @_dev: Address of the platform_device structure + * zynqmp_qspi_suspend - Suspend method for the QSPI driver + * @dev: Address of the platform_device structure * * This function stops the QSPI driver queue and disables the QSPI controller * @@ -911,7 +1105,7 @@ static int __maybe_unused zynqmp_qspi_suspend(struct device *dev) } /** - * zynqmp_qspi_resume: Resume method for the QSPI driver + * zynqmp_qspi_resume - Resume method for the QSPI driver * @dev: Address of the platform_device structure * * The function starts the QSPI driver queue and initializes the QSPI @@ -938,10 +1132,12 @@ static int __maybe_unused zynqmp_qspi_resume(struct device *dev) return ret; } + zynqmp_qspi_init_hw(xqspi); spi_master_resume(master); clk_disable(xqspi->refclk); clk_disable(xqspi->pclk); + return 0; } @@ -994,14 +1190,38 @@ static int __maybe_unused zynqmp_runtime_resume(struct device *dev) return 0; } +static int __maybe_unused zynqmp_runtime_idle(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct spi_master *master = platform_get_drvdata(pdev); + struct zynqmp_qspi *xqspi = spi_master_get_devdata(master); + u32 value; + + value = zynqmp_gqspi_read(xqspi, GQSPI_EN_OFST); + if (value) + return -EBUSY; + + return 0; +} + static const struct dev_pm_ops zynqmp_qspi_dev_pm_ops = { SET_RUNTIME_PM_OPS(zynqmp_runtime_suspend, - zynqmp_runtime_resume, NULL) + zynqmp_runtime_resume, zynqmp_runtime_idle) SET_SYSTEM_SLEEP_PM_OPS(zynqmp_qspi_suspend, zynqmp_qspi_resume) }; +static const struct qspi_platform_data versal_qspi_def = { + .quirks = QSPI_QUIRK_HAS_TAPDELAY, +}; + +static const struct of_device_id zynqmp_qspi_of_match[] = { + { .compatible = "xlnx,zynqmp-qspi-1.0"}, + { .compatible = "xlnx,versal-qspi-1.0", .data = &versal_qspi_def }, + { /* End of table */ } +}; + /** - * zynqmp_qspi_probe: Probe method for the QSPI driver + * zynqmp_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. @@ -1015,6 +1235,11 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) struct zynqmp_qspi *xqspi; struct resource *res; struct device *dev = &pdev->dev; + struct device_node *nc; + const struct of_device_id *match; + u32 num_cs; + u32 rx_bus_width; + u32 tx_bus_width; eemi_ops = zynqmp_pm_get_eemi_ops(); if (IS_ERR(eemi_ops)) @@ -1028,6 +1253,14 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; platform_set_drvdata(pdev, master); + match = of_match_node(zynqmp_qspi_of_match, pdev->dev.of_node); + if (match) { + const struct qspi_platform_data *p_data = match->data; + + if (p_data && (p_data->quirks & QSPI_QUIRK_HAS_TAPDELAY)) + xqspi->has_tapdelay = true; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); xqspi->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(xqspi->regs)) { @@ -1066,11 +1299,16 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + + if (of_property_read_bool(pdev->dev.of_node, "has-io-mode")) + xqspi->io_mode = true; + /* QSPI controller initializations */ zynqmp_qspi_init_hw(xqspi); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); + xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; @@ -1085,8 +1323,37 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) goto clk_dis_all; } - master->num_chipselect = GQSPI_DEFAULT_NUM_CS; + xqspi->rx_bus_width = GQSPI_RX_BUS_WIDTH_SINGLE; + for_each_available_child_of_node(pdev->dev.of_node, nc) { + ret = of_property_read_u32(nc, "spi-rx-bus-width", + &rx_bus_width); + if (!ret) { + xqspi->rx_bus_width = rx_bus_width; + break; + } + } + if (ret) + dev_err(dev, "rx bus width not found\n"); + + xqspi->tx_bus_width = GQSPI_TX_BUS_WIDTH_SINGLE; + for_each_available_child_of_node(pdev->dev.of_node, nc) { + ret = of_property_read_u32(nc, "spi-tx-bus-width", + &tx_bus_width); + if (!ret) { + xqspi->tx_bus_width = tx_bus_width; + break; + } + } + if (ret) + dev_err(dev, "tx bus width not found\n"); + + ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); + if (ret < 0) + master->num_chipselect = GQSPI_DEFAULT_NUM_CS; + else + master->num_chipselect = num_cs; + dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); master->setup = zynqmp_qspi_setup; master->set_cs = zynqmp_qspi_chipselect; master->transfer_one = zynqmp_qspi_start_transfer; @@ -1097,6 +1364,8 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_MASK(8); master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; + xqspi->speed_hz = master->max_speed_hz; + master->auto_runtime_pm = true; if (master->dev.parent == NULL) master->dev.parent = &master->dev; @@ -1120,7 +1389,7 @@ remove_master: } /** - * zynqmp_qspi_remove: Remove method for the QSPI driver + * zynqmp_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 @@ -1145,11 +1414,6 @@ static int zynqmp_qspi_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id zynqmp_qspi_of_match[] = { - { .compatible = "xlnx,zynqmp-qspi-1.0", }, - { /* End of table */ } -}; - MODULE_DEVICE_TABLE(of, zynqmp_qspi_of_match); static struct platform_driver zynqmp_qspi_driver = { diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index be5b4b65c016..bb2bb9bfe4fe 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3056,6 +3056,14 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) } } + /* + * Data stripe option is selected if and only if when + * two chips are enabled + */ + if ((ctlr->flags & SPI_MASTER_DATA_STRIPE) + && !(ctlr->flags & SPI_MASTER_BOTH_CS)) + return -EINVAL; + /* Half-duplex links include original MicroWire, and ones with * only one data pin like SPI_3WIRE (switches direction) or where * either MOSI or MISO is missing. They can also be caused by |