diff options
| author | Mark Brown <broonie@kernel.org> | 2021-02-12 14:00:22 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2021-02-12 14:00:22 +0000 |
| commit | eec262d179ff60e8d12298ab2f118661040e0bf5 (patch) | |
| tree | 8f1d5b98419588e7e6a9f5a9fc294b0fca093930 /drivers/spi | |
| parent | 110bc220aaab2f90374d7d9a4f1b2a4c916705b2 (diff) | |
| parent | d2275139649bc34b8b5c3e33d26d991ab8a1364c (diff) | |
| download | linux-eec262d179ff60e8d12298ab2f118661040e0bf5.tar.gz linux-eec262d179ff60e8d12298ab2f118661040e0bf5.tar.bz2 linux-eec262d179ff60e8d12298ab2f118661040e0bf5.zip | |
Merge remote-tracking branch 'spi/for-5.12' into spi-next
Diffstat (limited to 'drivers/spi')
28 files changed, 2244 insertions, 2423 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index aadaea052f51..5aab7c6cc439 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -203,7 +203,7 @@ config SPI_CADENCE config SPI_CADENCE_QUADSPI tristate "Cadence Quad SPI controller" - depends on OF && (ARM || ARM64 || COMPILE_TEST) + depends on OF && (ARM || ARM64 || X86 || COMPILE_TEST) help Enable support for the Cadence Quad SPI Flash controller. @@ -292,13 +292,6 @@ config SPI_DLN2 This driver can also be built as a module. If so, the module will be called spi-dln2. -config SPI_EFM32 - tristate "EFM32 SPI controller" - depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST) - select SPI_BITBANG - help - Driver for the spi controller found on Energy Micro's EFM32 SoCs. - config SPI_EP93XX tristate "Cirrus Logic EP93xx SPI controller" depends on ARCH_EP93XX || COMPILE_TEST @@ -650,7 +643,7 @@ config SPI_RPCIF tristate "Renesas RPC-IF SPI driver" depends on RENESAS_RPCIF help - SPI driver for Renesas R-Car Gen3 RPC-IF. + SPI driver for Renesas R-Car Gen3 or RZ/G2 RPC-IF. config SPI_RSPI tristate "Renesas RSPI/QSPI controller" @@ -751,13 +744,6 @@ config SPI_SIFIVE help This exposes the SPI controller IP from SiFive. -config SPI_SIRF - tristate "CSR SiRFprimaII SPI controller" - depends on SIRF_DMA - select SPI_BITBANG - help - SPI driver for CSR SiRFprimaII SoCs - config SPI_SLAVE_MT27XX tristate "MediaTek SPI slave device" depends on ARCH_MEDIATEK || COMPILE_TEST @@ -843,6 +829,15 @@ config SPI_MXS help SPI driver for Freescale MXS devices. +config SPI_TEGRA210_QUAD + tristate "NVIDIA Tegra QSPI Controller" + depends on ARCH_TEGRA || COMPILE_TEST + depends on RESET_CONTROLLER + help + QSPI driver for NVIDIA Tegra QSPI Controller interface. This + controller is different from the SPI controller and is available + on Tegra SoCs starting from Tegra210. + config SPI_TEGRA114 tristate "NVIDIA Tegra114 SPI Controller" depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST @@ -885,12 +880,6 @@ config SPI_TOPCLIFF_PCH This driver also supports the ML7213/ML7223/ML7831, a companion chip for the Atom E6xx series and compatible with the Intel EG20T PCH. -config SPI_TXX9 - tristate "Toshiba TXx9 SPI controller" - depends on GPIOLIB && (CPU_TX49XX || COMPILE_TEST) - help - SPI driver for Toshiba TXx9 MIPS SoCs - config SPI_UNIPHIER tristate "Socionext UniPhier SPI Controller" depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 6fea5821662e..0f06fc0813c6 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -42,7 +42,6 @@ spi-dw-$(CONFIG_SPI_DW_DMA) += spi-dw-dma.o obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1.o obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o -obj-$(CONFIG_SPI_EFM32) += spi-efm32.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o obj-$(CONFIG_SPI_FALCON) += spi-falcon.o obj-$(CONFIG_SPI_FSI) += spi-fsi.o @@ -94,6 +93,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom-qspi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o +obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o @@ -105,7 +105,6 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o -obj-$(CONFIG_SPI_SIRF) += spi-sirf.o obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o obj-$(CONFIG_SPI_SPRD) += spi-sprd.o obj-$(CONFIG_SPI_SPRD_ADI) += spi-sprd-adi.o @@ -115,6 +114,7 @@ obj-$(CONFIG_SPI_ST_SSC4) += spi-st-ssc4.o obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o obj-$(CONFIG_SPI_SYNQUACER) += spi-synquacer.o +obj-$(CONFIG_SPI_TEGRA210_QUAD) += spi-tegra210-quad.o obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o @@ -122,7 +122,6 @@ obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o spi-thunderx-objs := spi-cavium.o spi-cavium-thunderx.o obj-$(CONFIG_SPI_THUNDERX) += spi-thunderx.o obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o -obj-$(CONFIG_SPI_TXX9) += spi-txx9.o obj-$(CONFIG_SPI_UNIPHIER) += spi-uniphier.o obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 10bc5390ab91..95d4fa32c299 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -657,6 +657,7 @@ static int __maybe_unused atmel_qspi_suspend(struct device *dev) struct spi_controller *ctrl = dev_get_drvdata(dev); struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); + atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR); clk_disable_unprepare(aq->qspick); clk_disable_unprepare(aq->pclk); diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 948396b382d7..f429436082af 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1590,7 +1590,7 @@ static int atmel_spi_probe(struct platform_device *pdev) if (ret == 0) { as->use_dma = true; } else if (ret == -EPROBE_DEFER) { - return ret; + goto out_unmap_regs; } } else if (as->caps.has_pdc_support) { as->use_pdc = true; diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index dfb7196f4caf..4b59a1b1bf7e 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -26,7 +26,7 @@ #include <asm/mach-au1x00/au1550_spi.h> -static unsigned usedma = 1; +static unsigned int usedma = 1; module_param(usedma, uint, 0644); /* @@ -43,9 +43,9 @@ struct au1550_spi { volatile psc_spi_t __iomem *regs; int irq; - unsigned len; - unsigned tx_count; - unsigned rx_count; + unsigned int len; + unsigned int tx_count; + unsigned int rx_count; const u8 *tx; u8 *rx; @@ -56,14 +56,14 @@ struct au1550_spi { struct completion master_done; - unsigned usedma; + unsigned int usedma; u32 dma_tx_id; u32 dma_rx_id; u32 dma_tx_ch; u32 dma_rx_ch; u8 *dma_rx_tmpbuf; - unsigned dma_rx_tmpbuf_size; + unsigned int dma_rx_tmpbuf_size; u32 dma_rx_tmpbuf_addr; struct spi_master *master; @@ -74,8 +74,7 @@ struct au1550_spi { /* we use an 8-bit memory device for dma transfers to/from spi fifo */ -static dbdev_tab_t au1550_spi_mem_dbdev = -{ +static dbdev_tab_t au1550_spi_mem_dbdev = { .dev_id = DBDMA_MEM_CHAN, .dev_flags = DEV_FLAGS_ANYUSE|DEV_FLAGS_SYNC, .dev_tsize = 0, @@ -99,7 +98,7 @@ static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw); * BRG valid range is 4..63 * DIV valid range is 0..3 */ -static u32 au1550_spi_baudcfg(struct au1550_spi *hw, unsigned speed_hz) +static u32 au1550_spi_baudcfg(struct au1550_spi *hw, unsigned int speed_hz) { u32 mainclk_hz = hw->pdata->mainclk_hz; u32 div, brg; @@ -161,7 +160,7 @@ static void au1550_spi_reset_fifos(struct au1550_spi *hw) static void au1550_spi_chipsel(struct spi_device *spi, int value) { struct au1550_spi *hw = spi_master_get_devdata(spi->master); - unsigned cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; + unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; u32 cfg, stat; switch (value) { @@ -221,7 +220,7 @@ static void au1550_spi_chipsel(struct spi_device *spi, int value) static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) { struct au1550_spi *hw = spi_master_get_devdata(spi->master); - unsigned bpw, hz; + unsigned int bpw, hz; u32 cfg, stat; if (t) { @@ -276,7 +275,7 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) * spi master done event irq is not generated unless rx fifo is empty (emptied) * so we need rx tmp buffer to use for rx dma if user does not provide one */ -static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned size) +static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned int size) { hw->dma_rx_tmpbuf = kmalloc(size, GFP_KERNEL); if (!hw->dma_rx_tmpbuf) @@ -399,10 +398,10 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t) DMA_FROM_DEVICE); } /* unmap buffers if mapped above */ - if (t->rx_buf && t->rx_dma == 0 ) + if (t->rx_buf && t->rx_dma == 0) dma_unmap_single(hw->dev, dma_rx_addr, t->len, DMA_FROM_DEVICE); - if (t->tx_buf && t->tx_dma == 0 ) + if (t->tx_buf && t->tx_dma == 0) dma_unmap_single(hw->dev, dma_tx_addr, t->len, DMA_TO_DEVICE); @@ -447,8 +446,8 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw) "dma transfer: receive FIFO overflow!\n"); else dev_err(hw->dev, - "dma transfer: unexpected SPI error " - "(event=0x%x stat=0x%x)!\n", evnt, stat); + "dma transfer: unexpected SPI error (event=0x%x stat=0x%x)!\n", + evnt, stat); complete(&hw->master_done); return IRQ_HANDLED; @@ -493,12 +492,12 @@ static void au1550_spi_tx_word_##size(struct au1550_spi *hw) \ wmb(); /* drain writebuffer */ \ } -AU1550_SPI_RX_WORD(8,0xff) -AU1550_SPI_RX_WORD(16,0xffff) -AU1550_SPI_RX_WORD(32,0xffffff) -AU1550_SPI_TX_WORD(8,0xff) -AU1550_SPI_TX_WORD(16,0xffff) -AU1550_SPI_TX_WORD(32,0xffffff) +AU1550_SPI_RX_WORD(8, 0xff) +AU1550_SPI_RX_WORD(16, 0xffff) +AU1550_SPI_RX_WORD(32, 0xffffff) +AU1550_SPI_TX_WORD(8, 0xff) +AU1550_SPI_TX_WORD(16, 0xffff) +AU1550_SPI_TX_WORD(32, 0xffffff) static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t) { @@ -567,8 +566,8 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw) au1550_spi_mask_ack_all(hw); au1550_spi_reset_fifos(hw); dev_err(hw->dev, - "pio transfer: unexpected SPI error " - "(event=0x%x stat=0x%x)!\n", evnt, stat); + "pio transfer: unexpected SPI error (event=0x%x stat=0x%x)!\n", + evnt, stat); complete(&hw->master_done); return IRQ_HANDLED; } @@ -636,12 +635,14 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw) static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) { struct au1550_spi *hw = spi_master_get_devdata(spi->master); + return hw->txrx_bufs(spi, t); } static irqreturn_t au1550_spi_irq(int irq, void *dev) { struct au1550_spi *hw = dev; + return hw->irq_callback(hw); } @@ -872,6 +873,7 @@ static int au1550_spi_probe(struct platform_device *pdev) { int min_div = (2 << 0) * (2 * (4 + 1)); int max_div = (2 << 3) * (2 * (63 + 1)); + master->max_speed_hz = hw->pdata->mainclk_hz / min_div; master->min_speed_hz = hw->pdata->mainclk_hz / (max_div + 1) + 1; @@ -972,8 +974,7 @@ static int __init au1550_spi_init(void) if (usedma) { ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev); if (!ddma_memid) - printk(KERN_ERR "au1550-spi: cannot add memory" - "dbdma device\n"); + printk(KERN_ERR "au1550-spi: cannot add memory dbdma device\n"); } return platform_driver_register(&au1550_spi_drv); } diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index c028446c7460..707fe3a5d8ef 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -881,7 +881,7 @@ static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi, * when using flex mode we need to send * the upper address byte to bspi */ - if (bcm_qspi_bspi_ver_three(qspi) == false) { + if (!bcm_qspi_bspi_ver_three(qspi)) { addr = from & 0xff000000; bcm_qspi_write(qspi, BSPI, BSPI_BSPI_FLASH_UPPER_ADDR_BYTE, addr); diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 197485f2c2b2..8965fe61c8b4 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -386,7 +386,7 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) /* Transfer complete - reset SPI HW */ bcm2835_spi_reset_hw(bs); /* wake up the framework */ - complete(&bs->ctlr->xfer_completion); + spi_finalize_current_transfer(bs->ctlr); } return IRQ_HANDLED; @@ -608,7 +608,7 @@ static void bcm2835_spi_dma_rx_done(void *data) bcm2835_spi_reset_hw(bs); /* and mark as completed */; - complete(&ctlr->xfer_completion); + spi_finalize_current_transfer(ctlr); } /** @@ -640,7 +640,7 @@ static void bcm2835_spi_dma_tx_done(void *data) bcm2835_spi_undo_prologue(bs); bcm2835_spi_reset_hw(bs); - complete(&ctlr->xfer_completion); + spi_finalize_current_transfer(ctlr); } /** @@ -1307,6 +1307,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk), "could not get clk\n"); + ctlr->max_speed_hz = clk_get_rate(bs->clk) / 2; + bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) return bs->irq ? bs->irq : -ENODEV; diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 1a26865c42f8..75589ac6e95f 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -254,7 +254,7 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) /* and if rx_len is 0 then disable interrupts and wake up completion */ if (!bs->rx_len) { bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); - complete(&master->xfer_completion); + spi_finalize_current_transfer(master); } return IRQ_HANDLED; diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index ba7d40c2922f..442cc7c53a47 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -52,6 +52,7 @@ struct cqspi_flash_pdata { u8 inst_width; u8 addr_width; u8 data_width; + bool dtr; u8 cs; }; @@ -75,6 +76,7 @@ struct cqspi_st { bool is_decoded_cs; u32 fifo_depth; u32 fifo_width; + u32 num_chipselect; bool rclk_en; u32 trigger_address; u32 wr_delay; @@ -111,6 +113,8 @@ struct cqspi_driver_platdata { #define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10 #define CQSPI_REG_CONFIG_DMA_MASK BIT(15) #define CQSPI_REG_CONFIG_BAUD_LSB 19 +#define CQSPI_REG_CONFIG_DTR_PROTO BIT(24) +#define CQSPI_REG_CONFIG_DUAL_OPCODE BIT(30) #define CQSPI_REG_CONFIG_IDLE_LSB 31 #define CQSPI_REG_CONFIG_CHIPSELECT_MASK 0xF #define CQSPI_REG_CONFIG_BAUD_MASK 0xF @@ -173,6 +177,9 @@ struct cqspi_driver_platdata { #define CQSPI_REG_SDRAMLEVEL_RD_MASK 0xFFFF #define CQSPI_REG_SDRAMLEVEL_WR_MASK 0xFFFF +#define CQSPI_REG_WR_COMPLETION_CTRL 0x38 +#define CQSPI_REG_WR_DISABLE_AUTO_POLL BIT(14) + #define CQSPI_REG_IRQSTATUS 0x40 #define CQSPI_REG_IRQMASK 0x44 @@ -188,6 +195,7 @@ struct cqspi_driver_platdata { #define CQSPI_REG_CMDCTRL 0x90 #define CQSPI_REG_CMDCTRL_EXECUTE_MASK BIT(0) #define CQSPI_REG_CMDCTRL_INPROGRESS_MASK BIT(1) +#define CQSPI_REG_CMDCTRL_DUMMY_LSB 7 #define CQSPI_REG_CMDCTRL_WR_BYTES_LSB 12 #define CQSPI_REG_CMDCTRL_WR_EN_LSB 15 #define CQSPI_REG_CMDCTRL_ADD_BYTES_LSB 16 @@ -198,6 +206,7 @@ struct cqspi_driver_platdata { #define CQSPI_REG_CMDCTRL_WR_BYTES_MASK 0x7 #define CQSPI_REG_CMDCTRL_ADD_BYTES_MASK 0x3 #define CQSPI_REG_CMDCTRL_RD_BYTES_MASK 0x7 +#define CQSPI_REG_CMDCTRL_DUMMY_MASK 0x1F #define CQSPI_REG_INDIRECTWR 0x70 #define CQSPI_REG_INDIRECTWR_START_MASK BIT(0) @@ -214,6 +223,14 @@ struct cqspi_driver_platdata { #define CQSPI_REG_CMDWRITEDATALOWER 0xA8 #define CQSPI_REG_CMDWRITEDATAUPPER 0xAC +#define CQSPI_REG_POLLING_STATUS 0xB0 +#define CQSPI_REG_POLLING_STATUS_DUMMY_LSB 16 + +#define CQSPI_REG_OP_EXT_LOWER 0xE0 +#define CQSPI_REG_OP_EXT_READ_LSB 24 +#define CQSPI_REG_OP_EXT_WRITE_LSB 16 +#define CQSPI_REG_OP_EXT_STIG_LSB 0 + /* Interrupt status bits */ #define CQSPI_REG_IRQ_MODE_ERR BIT(0) #define CQSPI_REG_IRQ_UNDERFLOW BIT(1) @@ -288,6 +305,80 @@ static unsigned int cqspi_calc_rdreg(struct cqspi_flash_pdata *f_pdata) return rdreg; } +static unsigned int cqspi_calc_dummy(const struct spi_mem_op *op, bool dtr) +{ + unsigned int dummy_clk; + + dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth); + if (dtr) + dummy_clk /= 2; + + return dummy_clk; +} + +static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata, + const struct spi_mem_op *op) +{ + f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE; + f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE; + f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; + f_pdata->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr; + + switch (op->data.buswidth) { + case 0: + break; + case 1: + f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; + break; + case 2: + f_pdata->data_width = CQSPI_INST_TYPE_DUAL; + break; + case 4: + f_pdata->data_width = CQSPI_INST_TYPE_QUAD; + break; + case 8: + f_pdata->data_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + + /* Right now we only support 8-8-8 DTR mode. */ + if (f_pdata->dtr) { + switch (op->cmd.buswidth) { + case 0: + break; + case 8: + f_pdata->inst_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + + switch (op->addr.buswidth) { + case 0: + break; + case 8: + f_pdata->addr_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + + switch (op->data.buswidth) { + case 0: + break; + case 8: + f_pdata->data_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + } + + return 0; +} + static int cqspi_wait_idle(struct cqspi_st *cqspi) { const unsigned int poll_idle_retry = 3; @@ -345,19 +436,85 @@ static int cqspi_exec_flash_cmd(struct cqspi_st *cqspi, unsigned int reg) return cqspi_wait_idle(cqspi); } +static int cqspi_setup_opcode_ext(struct cqspi_flash_pdata *f_pdata, + const struct spi_mem_op *op, + unsigned int shift) +{ + struct cqspi_st *cqspi = f_pdata->cqspi; + void __iomem *reg_base = cqspi->iobase; + unsigned int reg; + u8 ext; + + if (op->cmd.nbytes != 2) + return -EINVAL; + + /* Opcode extension is the LSB. */ + ext = op->cmd.opcode & 0xff; + + reg = readl(reg_base + CQSPI_REG_OP_EXT_LOWER); + reg &= ~(0xff << shift); + reg |= ext << shift; + writel(reg, reg_base + CQSPI_REG_OP_EXT_LOWER); + + return 0; +} + +static int cqspi_enable_dtr(struct cqspi_flash_pdata *f_pdata, + const struct spi_mem_op *op, unsigned int shift, + bool enable) +{ + struct cqspi_st *cqspi = f_pdata->cqspi; + void __iomem *reg_base = cqspi->iobase; + unsigned int reg; + int ret; + + reg = readl(reg_base + CQSPI_REG_CONFIG); + + /* + * We enable dual byte opcode here. The callers have to set up the + * extension opcode based on which type of operation it is. + */ + if (enable) { + reg |= CQSPI_REG_CONFIG_DTR_PROTO; + reg |= CQSPI_REG_CONFIG_DUAL_OPCODE; + + /* Set up command opcode extension. */ + ret = cqspi_setup_opcode_ext(f_pdata, op, shift); + if (ret) + return ret; + } else { + reg &= ~CQSPI_REG_CONFIG_DTR_PROTO; + reg &= ~CQSPI_REG_CONFIG_DUAL_OPCODE; + } + + writel(reg, reg_base + CQSPI_REG_CONFIG); + + return cqspi_wait_idle(cqspi); +} + static int cqspi_command_read(struct cqspi_flash_pdata *f_pdata, const struct spi_mem_op *op) { struct cqspi_st *cqspi = f_pdata->cqspi; void __iomem *reg_base = cqspi->iobase; u8 *rxbuf = op->data.buf.in; - u8 opcode = op->cmd.opcode; + u8 opcode; size_t n_rx = op->data.nbytes; unsigned int rdreg; unsigned int reg; + unsigned int dummy_clk; size_t read_len; int status; + status = cqspi_set_protocol(f_pdata, op); + if (status) + return status; + + status = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_STIG_LSB, + f_pdata->dtr); + if (status) + return status; + if (!n_rx || n_rx > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) { dev_err(&cqspi->pdev->dev, "Invalid input argument, len %zu rxbuf 0x%p\n", @@ -365,11 +522,24 @@ static int cqspi_command_read(struct cqspi_flash_pdata *f_pdata, return -EINVAL; } + if (f_pdata->dtr) + opcode = op->cmd.opcode >> 8; + else + opcode = op->cmd.opcode; + reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; rdreg = cqspi_calc_rdreg(f_pdata); writel(rdreg, reg_base + CQSPI_REG_RD_INSTR); + dummy_clk = cqspi_calc_dummy(op, f_pdata->dtr); + if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) + return -EOPNOTSUPP; + + if (dummy_clk) + reg |= (dummy_clk & CQSPI_REG_CMDCTRL_DUMMY_MASK) + << CQSPI_REG_CMDCTRL_DUMMY_LSB; + reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB); /* 0 means 1 byte. */ @@ -401,12 +571,22 @@ static int cqspi_command_write(struct cqspi_flash_pdata *f_pdata, { struct cqspi_st *cqspi = f_pdata->cqspi; void __iomem *reg_base = cqspi->iobase; - const u8 opcode = op->cmd.opcode; + u8 opcode; const u8 *txbuf = op->data.buf.out; size_t n_tx = op->data.nbytes; unsigned int reg; unsigned int data; size_t write_len; + int ret; + + ret = cqspi_set_protocol(f_pdata, op); + if (ret) + return ret; + + ret = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_STIG_LSB, + f_pdata->dtr); + if (ret) + return ret; if (n_tx > CQSPI_STIG_DATA_LEN_MAX || (n_tx && !txbuf)) { dev_err(&cqspi->pdev->dev, @@ -415,6 +595,14 @@ static int cqspi_command_write(struct cqspi_flash_pdata *f_pdata, return -EINVAL; } + reg = cqspi_calc_rdreg(f_pdata); + writel(reg, reg_base + CQSPI_REG_RD_INSTR); + + if (f_pdata->dtr) + opcode = op->cmd.opcode >> 8; + else + opcode = op->cmd.opcode; + reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; if (op->addr.nbytes) { @@ -454,14 +642,27 @@ static int cqspi_read_setup(struct cqspi_flash_pdata *f_pdata, void __iomem *reg_base = cqspi->iobase; unsigned int dummy_clk = 0; unsigned int reg; + int ret; + u8 opcode; + + ret = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_READ_LSB, + f_pdata->dtr); + if (ret) + return ret; - reg = op->cmd.opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB; + if (f_pdata->dtr) + opcode = op->cmd.opcode >> 8; + else + opcode = op->cmd.opcode; + + reg = opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB; reg |= cqspi_calc_rdreg(f_pdata); /* Setup dummy clock cycles */ - dummy_clk = op->dummy.nbytes * 8; + dummy_clk = cqspi_calc_dummy(op, f_pdata->dtr); + if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) - dummy_clk = CQSPI_DUMMY_CLKS_MAX; + return -EOPNOTSUPP; if (dummy_clk) reg |= (dummy_clk & CQSPI_REG_RD_INSTR_DUMMY_MASK) @@ -573,15 +774,43 @@ static int cqspi_write_setup(struct cqspi_flash_pdata *f_pdata, const struct spi_mem_op *op) { unsigned int reg; + int ret; struct cqspi_st *cqspi = f_pdata->cqspi; void __iomem *reg_base = cqspi->iobase; + u8 opcode; + + ret = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_WRITE_LSB, + f_pdata->dtr); + if (ret) + return ret; + + if (f_pdata->dtr) + opcode = op->cmd.opcode >> 8; + else + opcode = op->cmd.opcode; /* Set opcode. */ - reg = op->cmd.opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB; + reg = opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB; + reg |= f_pdata->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB; + reg |= f_pdata->addr_width << CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB; writel(reg, reg_base + CQSPI_REG_WR_INSTR); reg = cqspi_calc_rdreg(f_pdata); writel(reg, reg_base + CQSPI_REG_RD_INSTR); + if (f_pdata->dtr) { + /* + * Some flashes like the cypress Semper flash expect a 4-byte + * dummy address with the Read SR command in DTR mode, but this + * controller does not support sending address with the Read SR + * command. So, disable write completion polling on the + * controller's side. spi-nor will take care of polling the + * status register. + */ + reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL; + writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + } + reg = readl(reg_base + CQSPI_REG_SIZE); reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; reg |= (op->addr.nbytes - 1); @@ -835,35 +1064,6 @@ static void cqspi_configure(struct cqspi_flash_pdata *f_pdata, cqspi_controller_enable(cqspi, 1); } -static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata, - const struct spi_mem_op *op) -{ - f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE; - f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE; - f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; - - if (op->data.dir == SPI_MEM_DATA_IN) { - switch (op->data.buswidth) { - case 1: - f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; - break; - case 2: - f_pdata->data_width = CQSPI_INST_TYPE_DUAL; - break; - case 4: - f_pdata->data_width = CQSPI_INST_TYPE_QUAD; - break; - case 8: - f_pdata->data_width = CQSPI_INST_TYPE_OCTAL; - break; - default: - return -EINVAL; - } - } - - return 0; -} - static ssize_t cqspi_write(struct cqspi_flash_pdata *f_pdata, const struct spi_mem_op *op) { @@ -881,7 +1081,16 @@ static ssize_t cqspi_write(struct cqspi_flash_pdata *f_pdata, if (ret) return ret; - if (cqspi->use_direct_mode && ((to + len) <= cqspi->ahb_size)) { + /* + * Some flashes like the Cypress Semper flash expect a dummy 4-byte + * address (all 0s) with the read status register command in DTR mode. + * But this controller does not support sending dummy address bytes to + * the flash when it is polling the write completion register in DTR + * mode. So, we can not use direct mode when in DTR mode for writing + * data. + */ + if (!f_pdata->dtr && cqspi->use_direct_mode && + ((to + len) <= cqspi->ahb_size)) { memcpy_toio(cqspi->ahb_base + to, buf, len); return cqspi_wait_idle(cqspi); } @@ -942,7 +1151,7 @@ static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata, dma_async_issue_pending(cqspi->rx_chan); if (!wait_for_completion_timeout(&cqspi->rx_dma_complete, - msecs_to_j |
