diff options
Diffstat (limited to 'drivers/spi/spi-xilinx.c')
-rw-r--r-- | drivers/spi/spi-xilinx.c | 897 |
1 files changed, 639 insertions, 258 deletions
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 8dd2bb99cb4d..eba54ebee3a3 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" @@ -76,14 +77,51 @@ #define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */ #define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */ +/* 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; + struct clk *axi_clk; + struct clk *axi4_clk; + struct clk *spi_clk; + struct device *dev; u8 *rx_ptr; /* pointer in the Tx buffer */ const u8 *tx_ptr; /* pointer in the Rx buffer */ u8 bytes_per_word; @@ -91,8 +129,69 @@ struct xilinx_spi { u32 cs_inactive; /* Level of the CS pins when inactive*/ unsigned int (*read_fn)(void __iomem *); void (*write_fn)(u32, void __iomem *); + 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) static void xspi_write32(u32 val, void __iomem *addr) { iowrite32(val, addr); @@ -113,53 +212,15 @@ 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; @@ -183,49 +244,106 @@ static void xspi_init_hw(struct xilinx_spi *xspi) 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) - */ - - cs = xspi->cs_inactive; - cs ^= BIT(spi->chip_select); +/** + * 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 void xilinx_spi_startup_block(struct xilinx_spi *xspi, u32 cs_num) +{ + void __iomem *regs_base = xspi->regs; + u32 chip_sel, config_reg, status_reg; /* Activate the chip select */ - xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET); + 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); } -/* spi_bitbang requires custom setup_transfer() to be defined if there is a - * custom txrx_bufs(). +/** + * xilinx_spi_setup_transfer - Configure SPI controller for specified + * transfer + * @spi: Pointer to the spi_device structure + * @t: 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 xilinx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); + u32 config_reg; + + config_reg = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); + /* Set the QSPI clock phase and clock polarity */ + config_reg &= ~(XSPI_CR_CPHA | XSPI_CR_CPOL); + if (spi->mode & SPI_CPHA) + config_reg |= XSPI_CR_CPHA; + if (spi->mode & SPI_CPOL) + config_reg |= XSPI_CR_CPOL; + if (spi->mode & SPI_LSB_FIRST) + config_reg |= XSPI_CR_LSB_FIRST; + xspi->write_fn(config_reg, xspi->regs + XSPI_CR_OFFSET); if (spi->mode & SPI_CS_HIGH) xspi->cs_inactive &= ~BIT(spi->chip_select); @@ -235,104 +353,257 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi, 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) { - 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); + 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 = xilinx_spi_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 *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; + xilinx_spi_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; + cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET); + cr |= XSPI_CR_ENABLE; + xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET); - 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--; - } - } + 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; + + ret = clk_enable(xspi->axi_clk); + if (ret) { + dev_err(dev, "Can not enable AXI clock\n"); + return ret; + } + + ret = clk_enable(xspi->axi4_clk); + if (ret) { + dev_err(dev, "Can not enable AXI4 clock\n"); + goto clk_disable_axi_clk; - remaining_words -= n_words; } - 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->spi_clk); + if (ret) { + dev_err(dev, "Can not enable SPI clock\n"); + goto clk_disable_axi4_clk; } - return t->len; + 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; +} + +/** + * 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 int __maybe_unused xilinx_spi_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct xilinx_spi *xspi = spi_master_get_devdata(master); + int ret = 0; + + if (!pm_runtime_suspended(dev)) { + ret = xilinx_spi_runtime_resume(dev); + if (ret < 0) + return ret; + } + + ret = spi_master_resume(master); + if (ret < 0) { + clk_disable(xspi->axi_clk); + clk_disable(xspi->axi4_clk); + clk_disable(xspi->spi_clk); + } + + return ret; +} + +/** + * 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) +{ + struct spi_master *master = dev_get_drvdata(dev); + int ret = 0; + + ret = spi_master_suspend(master); + if (ret) + return ret; + + if (!pm_runtime_suspended(dev)) + xilinx_spi_runtime_suspend(dev); + + xspi_unprepare_transfer_hardware(master); + + return ret; +} + +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) +}; /* This driver supports single master mode only. Hence Tx FIFO Empty * is the only interrupt we care about. @@ -341,112 +612,163 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) */ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) { - struct xilinx_spi *xspi = 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; /* 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 */ - complete(&xspi->done); - return IRQ_HANDLED; + 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; } - return IRQ_NONE; -} - -static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi) -{ - u8 sr; - int n_words = 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); - - /* 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)); + 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 n_words; + return status; } -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 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; + u32 cs_num; struct spi_master *master; - u32 tmp; - u8 i; + struct device_node *nc; + u32 tmp, rx_bus_width, fifo_size; + bool startup_block; - 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); - ret = of_property_read_u32(pdev->dev.of_node, - "xlnx,num-transfer-bits", - &bits_per_word); - if (ret) - bits_per_word = 8; - } - - 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)) { ret = PTR_ERR(xspi->regs); goto put_master; } + 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; + } + } - master->bus_num = pdev->id; - master->num_chipselect = num_cs; - master->dev.of_node = pdev->dev.of_node; + 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 @@ -466,62 +788,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; } @@ -529,12 +901,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); |