179b8a705SPatrice Chotard // SPDX-License-Identifier: GPL-2.0 279b8a705SPatrice Chotard /* 379b8a705SPatrice Chotard * Copyright (C) STMicroelectronics 2025 - All Rights Reserved 479b8a705SPatrice Chotard */ 579b8a705SPatrice Chotard 679b8a705SPatrice Chotard #include <linux/bitfield.h> 779b8a705SPatrice Chotard #include <linux/clk.h> 879b8a705SPatrice Chotard #include <linux/delay.h> 979b8a705SPatrice Chotard #include <linux/dma-mapping.h> 1079b8a705SPatrice Chotard #include <linux/dmaengine.h> 1179b8a705SPatrice Chotard #include <linux/err.h> 1279b8a705SPatrice Chotard #include <linux/errno.h> 13*cc1273dfSPeng Fan #include <linux/gpio/consumer.h> 1479b8a705SPatrice Chotard #include <linux/interrupt.h> 1579b8a705SPatrice Chotard #include <linux/io.h> 1679b8a705SPatrice Chotard #include <linux/iopoll.h> 1779b8a705SPatrice Chotard #include <linux/mfd/syscon.h> 1879b8a705SPatrice Chotard #include <linux/module.h> 1979b8a705SPatrice Chotard #include <linux/mutex.h> 2079b8a705SPatrice Chotard #include <linux/of.h> 2179b8a705SPatrice Chotard #include <linux/of_address.h> 2279b8a705SPatrice Chotard #include <linux/of_device.h> 2379b8a705SPatrice Chotard #include <linux/of_reserved_mem.h> 2479b8a705SPatrice Chotard #include <linux/pinctrl/consumer.h> 2579b8a705SPatrice Chotard #include <linux/platform_device.h> 2679b8a705SPatrice Chotard #include <linux/pm_runtime.h> 2779b8a705SPatrice Chotard #include <linux/reset.h> 2879b8a705SPatrice Chotard #include <linux/sizes.h> 2979b8a705SPatrice Chotard #include <linux/spi/spi-mem.h> 3079b8a705SPatrice Chotard #include <linux/types.h> 3179b8a705SPatrice Chotard 3279b8a705SPatrice Chotard #define OSPI_CR 0x00 3379b8a705SPatrice Chotard #define CR_EN BIT(0) 3479b8a705SPatrice Chotard #define CR_ABORT BIT(1) 3579b8a705SPatrice Chotard #define CR_DMAEN BIT(2) 3679b8a705SPatrice Chotard #define CR_FTHRES_SHIFT 8 3779b8a705SPatrice Chotard #define CR_TEIE BIT(16) 3879b8a705SPatrice Chotard #define CR_TCIE BIT(17) 3979b8a705SPatrice Chotard #define CR_SMIE BIT(19) 4079b8a705SPatrice Chotard #define CR_APMS BIT(22) 4179b8a705SPatrice Chotard #define CR_CSSEL BIT(24) 4279b8a705SPatrice Chotard #define CR_FMODE_MASK GENMASK(29, 28) 4379b8a705SPatrice Chotard #define CR_FMODE_INDW (0U) 4479b8a705SPatrice Chotard #define CR_FMODE_INDR (1U) 4579b8a705SPatrice Chotard #define CR_FMODE_APM (2U) 4679b8a705SPatrice Chotard #define CR_FMODE_MM (3U) 4779b8a705SPatrice Chotard 4879b8a705SPatrice Chotard #define OSPI_DCR1 0x08 4979b8a705SPatrice Chotard #define DCR1_DLYBYP BIT(3) 5079b8a705SPatrice Chotard #define DCR1_DEVSIZE_MASK GENMASK(20, 16) 5179b8a705SPatrice Chotard #define DCR1_MTYP_MASK GENMASK(26, 24) 5279b8a705SPatrice Chotard #define DCR1_MTYP_MX_MODE 1 5379b8a705SPatrice Chotard #define DCR1_MTYP_HP_MEMMODE 4 5479b8a705SPatrice Chotard 5579b8a705SPatrice Chotard #define OSPI_DCR2 0x0c 5679b8a705SPatrice Chotard #define DCR2_PRESC_MASK GENMASK(7, 0) 5779b8a705SPatrice Chotard 5879b8a705SPatrice Chotard #define OSPI_SR 0x20 5979b8a705SPatrice Chotard #define SR_TEF BIT(0) 6079b8a705SPatrice Chotard #define SR_TCF BIT(1) 6179b8a705SPatrice Chotard #define SR_FTF BIT(2) 6279b8a705SPatrice Chotard #define SR_SMF BIT(3) 6379b8a705SPatrice Chotard #define SR_BUSY BIT(5) 6479b8a705SPatrice Chotard 6579b8a705SPatrice Chotard #define OSPI_FCR 0x24 6679b8a705SPatrice Chotard #define FCR_CTEF BIT(0) 6779b8a705SPatrice Chotard #define FCR_CTCF BIT(1) 6879b8a705SPatrice Chotard #define FCR_CSMF BIT(3) 6979b8a705SPatrice Chotard 7079b8a705SPatrice Chotard #define OSPI_DLR 0x40 7179b8a705SPatrice Chotard #define OSPI_AR 0x48 7279b8a705SPatrice Chotard #define OSPI_DR 0x50 7379b8a705SPatrice Chotard #define OSPI_PSMKR 0x80 7479b8a705SPatrice Chotard #define OSPI_PSMAR 0x88 7579b8a705SPatrice Chotard 7679b8a705SPatrice Chotard #define OSPI_CCR 0x100 7779b8a705SPatrice Chotard #define CCR_IMODE_MASK GENMASK(2, 0) 7879b8a705SPatrice Chotard #define CCR_IDTR BIT(3) 7979b8a705SPatrice Chotard #define CCR_ISIZE_MASK GENMASK(5, 4) 8079b8a705SPatrice Chotard #define CCR_ADMODE_MASK GENMASK(10, 8) 8179b8a705SPatrice Chotard #define CCR_ADMODE_8LINES 4 8279b8a705SPatrice Chotard #define CCR_ADDTR BIT(11) 8379b8a705SPatrice Chotard #define CCR_ADSIZE_MASK GENMASK(13, 12) 8479b8a705SPatrice Chotard #define CCR_ADSIZE_32BITS 3 8579b8a705SPatrice Chotard #define CCR_DMODE_MASK GENMASK(26, 24) 8679b8a705SPatrice Chotard #define CCR_DMODE_8LINES 4 8779b8a705SPatrice Chotard #define CCR_DQSE BIT(29) 8879b8a705SPatrice Chotard #define CCR_DDTR BIT(27) 8979b8a705SPatrice Chotard #define CCR_BUSWIDTH_0 0x0 9079b8a705SPatrice Chotard #define CCR_BUSWIDTH_1 0x1 9179b8a705SPatrice Chotard #define CCR_BUSWIDTH_2 0x2 9279b8a705SPatrice Chotard #define CCR_BUSWIDTH_4 0x3 9379b8a705SPatrice Chotard #define CCR_BUSWIDTH_8 0x4 9479b8a705SPatrice Chotard 9579b8a705SPatrice Chotard #define OSPI_TCR 0x108 9679b8a705SPatrice Chotard #define TCR_DCYC_MASK GENMASK(4, 0) 9779b8a705SPatrice Chotard #define TCR_DHQC BIT(28) 9879b8a705SPatrice Chotard #define TCR_SSHIFT BIT(30) 9979b8a705SPatrice Chotard 10079b8a705SPatrice Chotard #define OSPI_IR 0x110 10179b8a705SPatrice Chotard 10279b8a705SPatrice Chotard #define STM32_OSPI_MAX_MMAP_SZ SZ_256M 10379b8a705SPatrice Chotard #define STM32_OSPI_MAX_NORCHIP 2 10479b8a705SPatrice Chotard 10579b8a705SPatrice Chotard #define STM32_FIFO_TIMEOUT_US 30000 10679b8a705SPatrice Chotard #define STM32_ABT_TIMEOUT_US 100000 10779b8a705SPatrice Chotard #define STM32_COMP_TIMEOUT_MS 5000 10879b8a705SPatrice Chotard #define STM32_BUSY_TIMEOUT_US 100000 10979b8a705SPatrice Chotard 11079b8a705SPatrice Chotard 11179b8a705SPatrice Chotard #define STM32_AUTOSUSPEND_DELAY -1 11279b8a705SPatrice Chotard 11379b8a705SPatrice Chotard struct stm32_ospi { 11479b8a705SPatrice Chotard struct device *dev; 11579b8a705SPatrice Chotard struct spi_controller *ctrl; 11679b8a705SPatrice Chotard struct clk *clk; 11779b8a705SPatrice Chotard struct reset_control *rstc; 11879b8a705SPatrice Chotard 11979b8a705SPatrice Chotard struct completion data_completion; 12079b8a705SPatrice Chotard struct completion match_completion; 12179b8a705SPatrice Chotard 12279b8a705SPatrice Chotard struct dma_chan *dma_chtx; 12379b8a705SPatrice Chotard struct dma_chan *dma_chrx; 12479b8a705SPatrice Chotard struct completion dma_completion; 12579b8a705SPatrice Chotard 12679b8a705SPatrice Chotard void __iomem *regs_base; 12779b8a705SPatrice Chotard void __iomem *mm_base; 12879b8a705SPatrice Chotard phys_addr_t regs_phys_base; 12979b8a705SPatrice Chotard resource_size_t mm_size; 13079b8a705SPatrice Chotard u32 clk_rate; 13179b8a705SPatrice Chotard u32 fmode; 13279b8a705SPatrice Chotard u32 cr_reg; 13379b8a705SPatrice Chotard u32 dcr_reg; 13479b8a705SPatrice Chotard u32 flash_presc[STM32_OSPI_MAX_NORCHIP]; 13579b8a705SPatrice Chotard int irq; 13679b8a705SPatrice Chotard unsigned long status_timeout; 13779b8a705SPatrice Chotard 13879b8a705SPatrice Chotard /* 13979b8a705SPatrice Chotard * To protect device configuration, could be different between 14079b8a705SPatrice Chotard * 2 flash access 14179b8a705SPatrice Chotard */ 14279b8a705SPatrice Chotard struct mutex lock; 14379b8a705SPatrice Chotard }; 14479b8a705SPatrice Chotard 14579b8a705SPatrice Chotard static void stm32_ospi_read_fifo(u8 *val, void __iomem *addr) 14679b8a705SPatrice Chotard { 14779b8a705SPatrice Chotard *val = readb_relaxed(addr); 14879b8a705SPatrice Chotard } 14979b8a705SPatrice Chotard 15079b8a705SPatrice Chotard static void stm32_ospi_write_fifo(u8 *val, void __iomem *addr) 15179b8a705SPatrice Chotard { 15279b8a705SPatrice Chotard writeb_relaxed(*val, addr); 15379b8a705SPatrice Chotard } 15479b8a705SPatrice Chotard 15579b8a705SPatrice Chotard static int stm32_ospi_abort(struct stm32_ospi *ospi) 15679b8a705SPatrice Chotard { 15779b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 15879b8a705SPatrice Chotard u32 cr; 15979b8a705SPatrice Chotard int timeout; 16079b8a705SPatrice Chotard 16179b8a705SPatrice Chotard cr = readl_relaxed(regs_base + OSPI_CR) | CR_ABORT; 16279b8a705SPatrice Chotard writel_relaxed(cr, regs_base + OSPI_CR); 16379b8a705SPatrice Chotard 16479b8a705SPatrice Chotard /* wait clear of abort bit by hw */ 16579b8a705SPatrice Chotard timeout = readl_relaxed_poll_timeout_atomic(regs_base + OSPI_CR, 16679b8a705SPatrice Chotard cr, !(cr & CR_ABORT), 1, 16779b8a705SPatrice Chotard STM32_ABT_TIMEOUT_US); 16879b8a705SPatrice Chotard 16979b8a705SPatrice Chotard if (timeout) 17079b8a705SPatrice Chotard dev_err(ospi->dev, "%s abort timeout:%d\n", __func__, timeout); 17179b8a705SPatrice Chotard 17279b8a705SPatrice Chotard return timeout; 17379b8a705SPatrice Chotard } 17479b8a705SPatrice Chotard 17579b8a705SPatrice Chotard static int stm32_ospi_poll(struct stm32_ospi *ospi, u8 *buf, u32 len, bool read) 17679b8a705SPatrice Chotard { 17779b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 17879b8a705SPatrice Chotard void (*fifo)(u8 *val, void __iomem *addr); 17979b8a705SPatrice Chotard u32 sr; 18079b8a705SPatrice Chotard int ret; 18179b8a705SPatrice Chotard 18279b8a705SPatrice Chotard if (read) 18379b8a705SPatrice Chotard fifo = stm32_ospi_read_fifo; 18479b8a705SPatrice Chotard else 18579b8a705SPatrice Chotard fifo = stm32_ospi_write_fifo; 18679b8a705SPatrice Chotard 18779b8a705SPatrice Chotard while (len--) { 18879b8a705SPatrice Chotard ret = readl_relaxed_poll_timeout_atomic(regs_base + OSPI_SR, 18979b8a705SPatrice Chotard sr, sr & SR_FTF, 1, 19079b8a705SPatrice Chotard STM32_FIFO_TIMEOUT_US); 19179b8a705SPatrice Chotard if (ret) { 19279b8a705SPatrice Chotard dev_err(ospi->dev, "fifo timeout (len:%d stat:%#x)\n", 19379b8a705SPatrice Chotard len, sr); 19479b8a705SPatrice Chotard return ret; 19579b8a705SPatrice Chotard } 19679b8a705SPatrice Chotard fifo(buf++, regs_base + OSPI_DR); 19779b8a705SPatrice Chotard } 19879b8a705SPatrice Chotard 19979b8a705SPatrice Chotard return 0; 20079b8a705SPatrice Chotard } 20179b8a705SPatrice Chotard 20279b8a705SPatrice Chotard static int stm32_ospi_wait_nobusy(struct stm32_ospi *ospi) 20379b8a705SPatrice Chotard { 20479b8a705SPatrice Chotard u32 sr; 20579b8a705SPatrice Chotard 20679b8a705SPatrice Chotard return readl_relaxed_poll_timeout_atomic(ospi->regs_base + OSPI_SR, 20779b8a705SPatrice Chotard sr, !(sr & SR_BUSY), 1, 20879b8a705SPatrice Chotard STM32_BUSY_TIMEOUT_US); 20979b8a705SPatrice Chotard } 21079b8a705SPatrice Chotard 21179b8a705SPatrice Chotard static int stm32_ospi_wait_cmd(struct stm32_ospi *ospi) 21279b8a705SPatrice Chotard { 21379b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 21479b8a705SPatrice Chotard u32 cr, sr; 21579b8a705SPatrice Chotard int err = 0; 21679b8a705SPatrice Chotard 21779b8a705SPatrice Chotard if ((readl_relaxed(regs_base + OSPI_SR) & SR_TCF) || 21879b8a705SPatrice Chotard ospi->fmode == CR_FMODE_APM) 21979b8a705SPatrice Chotard goto out; 22079b8a705SPatrice Chotard 22179b8a705SPatrice Chotard reinit_completion(&ospi->data_completion); 22279b8a705SPatrice Chotard cr = readl_relaxed(regs_base + OSPI_CR); 22379b8a705SPatrice Chotard writel_relaxed(cr | CR_TCIE | CR_TEIE, regs_base + OSPI_CR); 22479b8a705SPatrice Chotard 22579b8a705SPatrice Chotard if (!wait_for_completion_timeout(&ospi->data_completion, 22679b8a705SPatrice Chotard msecs_to_jiffies(STM32_COMP_TIMEOUT_MS))) 22779b8a705SPatrice Chotard err = -ETIMEDOUT; 22879b8a705SPatrice Chotard 22979b8a705SPatrice Chotard sr = readl_relaxed(regs_base + OSPI_SR); 23079b8a705SPatrice Chotard if (sr & SR_TCF) 23179b8a705SPatrice Chotard /* avoid false timeout */ 23279b8a705SPatrice Chotard err = 0; 23379b8a705SPatrice Chotard if (sr & SR_TEF) 23479b8a705SPatrice Chotard err = -EIO; 23579b8a705SPatrice Chotard 23679b8a705SPatrice Chotard out: 23779b8a705SPatrice Chotard /* clear flags */ 23879b8a705SPatrice Chotard writel_relaxed(FCR_CTCF | FCR_CTEF, regs_base + OSPI_FCR); 23979b8a705SPatrice Chotard 24079b8a705SPatrice Chotard if (!err) 24179b8a705SPatrice Chotard err = stm32_ospi_wait_nobusy(ospi); 24279b8a705SPatrice Chotard 24379b8a705SPatrice Chotard return err; 24479b8a705SPatrice Chotard } 24579b8a705SPatrice Chotard 24679b8a705SPatrice Chotard static void stm32_ospi_dma_callback(void *arg) 24779b8a705SPatrice Chotard { 24879b8a705SPatrice Chotard struct completion *dma_completion = arg; 24979b8a705SPatrice Chotard 25079b8a705SPatrice Chotard complete(dma_completion); 25179b8a705SPatrice Chotard } 25279b8a705SPatrice Chotard 25379b8a705SPatrice Chotard static irqreturn_t stm32_ospi_irq(int irq, void *dev_id) 25479b8a705SPatrice Chotard { 25579b8a705SPatrice Chotard struct stm32_ospi *ospi = (struct stm32_ospi *)dev_id; 25679b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 25779b8a705SPatrice Chotard u32 cr, sr; 25879b8a705SPatrice Chotard 25979b8a705SPatrice Chotard cr = readl_relaxed(regs_base + OSPI_CR); 26079b8a705SPatrice Chotard sr = readl_relaxed(regs_base + OSPI_SR); 26179b8a705SPatrice Chotard 26279b8a705SPatrice Chotard if (cr & CR_SMIE && sr & SR_SMF) { 26379b8a705SPatrice Chotard /* disable irq */ 26479b8a705SPatrice Chotard cr &= ~CR_SMIE; 26579b8a705SPatrice Chotard writel_relaxed(cr, regs_base + OSPI_CR); 26679b8a705SPatrice Chotard complete(&ospi->match_completion); 26779b8a705SPatrice Chotard 26879b8a705SPatrice Chotard return IRQ_HANDLED; 26979b8a705SPatrice Chotard } 27079b8a705SPatrice Chotard 27179b8a705SPatrice Chotard if (sr & (SR_TEF | SR_TCF)) { 27279b8a705SPatrice Chotard /* disable irq */ 27379b8a705SPatrice Chotard cr &= ~CR_TCIE & ~CR_TEIE; 27479b8a705SPatrice Chotard writel_relaxed(cr, regs_base + OSPI_CR); 27579b8a705SPatrice Chotard complete(&ospi->data_completion); 27679b8a705SPatrice Chotard } 27779b8a705SPatrice Chotard 27879b8a705SPatrice Chotard return IRQ_HANDLED; 27979b8a705SPatrice Chotard } 28079b8a705SPatrice Chotard 28179b8a705SPatrice Chotard static void stm32_ospi_dma_setup(struct stm32_ospi *ospi, 28279b8a705SPatrice Chotard struct dma_slave_config *dma_cfg) 28379b8a705SPatrice Chotard { 28479b8a705SPatrice Chotard if (dma_cfg && ospi->dma_chrx) { 28579b8a705SPatrice Chotard if (dmaengine_slave_config(ospi->dma_chrx, dma_cfg)) { 28679b8a705SPatrice Chotard dev_err(ospi->dev, "dma rx config failed\n"); 28779b8a705SPatrice Chotard dma_release_channel(ospi->dma_chrx); 28879b8a705SPatrice Chotard ospi->dma_chrx = NULL; 28979b8a705SPatrice Chotard } 29079b8a705SPatrice Chotard } 29179b8a705SPatrice Chotard 29279b8a705SPatrice Chotard if (dma_cfg && ospi->dma_chtx) { 29379b8a705SPatrice Chotard if (dmaengine_slave_config(ospi->dma_chtx, dma_cfg)) { 29479b8a705SPatrice Chotard dev_err(ospi->dev, "dma tx config failed\n"); 29579b8a705SPatrice Chotard dma_release_channel(ospi->dma_chtx); 29679b8a705SPatrice Chotard ospi->dma_chtx = NULL; 29779b8a705SPatrice Chotard } 29879b8a705SPatrice Chotard } 29979b8a705SPatrice Chotard 30079b8a705SPatrice Chotard init_completion(&ospi->dma_completion); 30179b8a705SPatrice Chotard } 30279b8a705SPatrice Chotard 30379b8a705SPatrice Chotard static int stm32_ospi_tx_mm(struct stm32_ospi *ospi, 30479b8a705SPatrice Chotard const struct spi_mem_op *op) 30579b8a705SPatrice Chotard { 30679b8a705SPatrice Chotard memcpy_fromio(op->data.buf.in, ospi->mm_base + op->addr.val, 30779b8a705SPatrice Chotard op->data.nbytes); 30879b8a705SPatrice Chotard return 0; 30979b8a705SPatrice Chotard } 31079b8a705SPatrice Chotard 31179b8a705SPatrice Chotard static int stm32_ospi_tx_dma(struct stm32_ospi *ospi, 31279b8a705SPatrice Chotard const struct spi_mem_op *op) 31379b8a705SPatrice Chotard { 31479b8a705SPatrice Chotard struct dma_async_tx_descriptor *desc; 31579b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 31679b8a705SPatrice Chotard enum dma_transfer_direction dma_dir; 31779b8a705SPatrice Chotard struct dma_chan *dma_ch; 31879b8a705SPatrice Chotard struct sg_table sgt; 31979b8a705SPatrice Chotard dma_cookie_t cookie; 32079b8a705SPatrice Chotard u32 cr, t_out; 32179b8a705SPatrice Chotard int err; 32279b8a705SPatrice Chotard 32379b8a705SPatrice Chotard if (op->data.dir == SPI_MEM_DATA_IN) { 32479b8a705SPatrice Chotard dma_dir = DMA_DEV_TO_MEM; 32579b8a705SPatrice Chotard dma_ch = ospi->dma_chrx; 32679b8a705SPatrice Chotard } else { 32779b8a705SPatrice Chotard dma_dir = DMA_MEM_TO_DEV; 32879b8a705SPatrice Chotard dma_ch = ospi->dma_chtx; 32979b8a705SPatrice Chotard } 33079b8a705SPatrice Chotard 33179b8a705SPatrice Chotard /* 33279b8a705SPatrice Chotard * Spi_map_buf return -EINVAL if the buffer is not DMA-able 33379b8a705SPatrice Chotard * (DMA-able: in vmalloc | kmap | virt_addr_valid) 33479b8a705SPatrice Chotard */ 33579b8a705SPatrice Chotard err = spi_controller_dma_map_mem_op_data(ospi->ctrl, op, &sgt); 33679b8a705SPatrice Chotard if (err) 33779b8a705SPatrice Chotard return err; 33879b8a705SPatrice Chotard 33979b8a705SPatrice Chotard desc = dmaengine_prep_slave_sg(dma_ch, sgt.sgl, sgt.nents, 34079b8a705SPatrice Chotard dma_dir, DMA_PREP_INTERRUPT); 34179b8a705SPatrice Chotard if (!desc) { 34279b8a705SPatrice Chotard err = -ENOMEM; 34379b8a705SPatrice Chotard goto out_unmap; 34479b8a705SPatrice Chotard } 34579b8a705SPatrice Chotard 34679b8a705SPatrice Chotard cr = readl_relaxed(regs_base + OSPI_CR); 34779b8a705SPatrice Chotard 34879b8a705SPatrice Chotard reinit_completion(&ospi->dma_completion); 34979b8a705SPatrice Chotard desc->callback = stm32_ospi_dma_callback; 35079b8a705SPatrice Chotard desc->callback_param = &ospi->dma_completion; 35179b8a705SPatrice Chotard cookie = dmaengine_submit(desc); 35279b8a705SPatrice Chotard err = dma_submit_error(cookie); 35379b8a705SPatrice Chotard if (err) 35479b8a705SPatrice Chotard goto out; 35579b8a705SPatrice Chotard 35679b8a705SPatrice Chotard dma_async_issue_pending(dma_ch); 35779b8a705SPatrice Chotard 35879b8a705SPatrice Chotard writel_relaxed(cr | CR_DMAEN, regs_base + OSPI_CR); 35979b8a705SPatrice Chotard 36079b8a705SPatrice Chotard t_out = sgt.nents * STM32_COMP_TIMEOUT_MS; 36179b8a705SPatrice Chotard if (!wait_for_completion_timeout(&ospi->dma_completion, 36279b8a705SPatrice Chotard msecs_to_jiffies(t_out))) 36379b8a705SPatrice Chotard err = -ETIMEDOUT; 36479b8a705SPatrice Chotard 36579b8a705SPatrice Chotard if (err) 36679b8a705SPatrice Chotard dmaengine_terminate_all(dma_ch); 36779b8a705SPatrice Chotard 36879b8a705SPatrice Chotard out: 36979b8a705SPatrice Chotard writel_relaxed(cr & ~CR_DMAEN, regs_base + OSPI_CR); 37079b8a705SPatrice Chotard out_unmap: 37179b8a705SPatrice Chotard spi_controller_dma_unmap_mem_op_data(ospi->ctrl, op, &sgt); 37279b8a705SPatrice Chotard 37379b8a705SPatrice Chotard return err; 37479b8a705SPatrice Chotard } 37579b8a705SPatrice Chotard 37679b8a705SPatrice Chotard static int stm32_ospi_xfer(struct stm32_ospi *ospi, const struct spi_mem_op *op) 37779b8a705SPatrice Chotard { 37879b8a705SPatrice Chotard u8 *buf; 37979b8a705SPatrice Chotard 38079b8a705SPatrice Chotard if (!op->data.nbytes) 38179b8a705SPatrice Chotard return 0; 38279b8a705SPatrice Chotard 38379b8a705SPatrice Chotard if (ospi->fmode == CR_FMODE_MM) 38479b8a705SPatrice Chotard return stm32_ospi_tx_mm(ospi, op); 38579b8a705SPatrice Chotard else if (((op->data.dir == SPI_MEM_DATA_IN && ospi->dma_chrx) || 38679b8a705SPatrice Chotard (op->data.dir == SPI_MEM_DATA_OUT && ospi->dma_chtx)) && 38779b8a705SPatrice Chotard op->data.nbytes > 8) 38879b8a705SPatrice Chotard if (!stm32_ospi_tx_dma(ospi, op)) 38979b8a705SPatrice Chotard return 0; 39079b8a705SPatrice Chotard 39179b8a705SPatrice Chotard if (op->data.dir == SPI_MEM_DATA_IN) 39279b8a705SPatrice Chotard buf = op->data.buf.in; 39379b8a705SPatrice Chotard else 39479b8a705SPatrice Chotard buf = (u8 *)op->data.buf.out; 39579b8a705SPatrice Chotard 39679b8a705SPatrice Chotard return stm32_ospi_poll(ospi, buf, op->data.nbytes, 39779b8a705SPatrice Chotard op->data.dir == SPI_MEM_DATA_IN); 39879b8a705SPatrice Chotard } 39979b8a705SPatrice Chotard 40079b8a705SPatrice Chotard static int stm32_ospi_wait_poll_status(struct stm32_ospi *ospi, 40179b8a705SPatrice Chotard const struct spi_mem_op *op) 40279b8a705SPatrice Chotard { 40379b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 40479b8a705SPatrice Chotard u32 cr; 40579b8a705SPatrice Chotard 40679b8a705SPatrice Chotard reinit_completion(&ospi->match_completion); 40779b8a705SPatrice Chotard cr = readl_relaxed(regs_base + OSPI_CR); 40879b8a705SPatrice Chotard writel_relaxed(cr | CR_SMIE, regs_base + OSPI_CR); 40979b8a705SPatrice Chotard 41079b8a705SPatrice Chotard if (!wait_for_completion_timeout(&ospi->match_completion, 41179b8a705SPatrice Chotard msecs_to_jiffies(ospi->status_timeout))) { 41279b8a705SPatrice Chotard u32 sr = readl_relaxed(regs_base + OSPI_SR); 41379b8a705SPatrice Chotard 41479b8a705SPatrice Chotard /* Avoid false timeout */ 41579b8a705SPatrice Chotard if (!(sr & SR_SMF)) 41679b8a705SPatrice Chotard return -ETIMEDOUT; 41779b8a705SPatrice Chotard } 41879b8a705SPatrice Chotard 41979b8a705SPatrice Chotard writel_relaxed(FCR_CSMF, regs_base + OSPI_FCR); 42079b8a705SPatrice Chotard 42179b8a705SPatrice Chotard return 0; 42279b8a705SPatrice Chotard } 42379b8a705SPatrice Chotard 42479b8a705SPatrice Chotard static int stm32_ospi_get_mode(u8 buswidth) 42579b8a705SPatrice Chotard { 42679b8a705SPatrice Chotard switch (buswidth) { 42779b8a705SPatrice Chotard case 8: 42879b8a705SPatrice Chotard return CCR_BUSWIDTH_8; 42979b8a705SPatrice Chotard case 4: 43079b8a705SPatrice Chotard return CCR_BUSWIDTH_4; 43179b8a705SPatrice Chotard default: 43279b8a705SPatrice Chotard return buswidth; 43379b8a705SPatrice Chotard } 43479b8a705SPatrice Chotard } 43579b8a705SPatrice Chotard 43679b8a705SPatrice Chotard static int stm32_ospi_send(struct spi_device *spi, const struct spi_mem_op *op) 43779b8a705SPatrice Chotard { 43879b8a705SPatrice Chotard struct stm32_ospi *ospi = spi_controller_get_devdata(spi->controller); 43979b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 44079b8a705SPatrice Chotard u32 ccr, cr, dcr2, tcr; 44179b8a705SPatrice Chotard int timeout, err = 0, err_poll_status = 0; 44279b8a705SPatrice Chotard u8 cs = spi->chip_select[ffs(spi->cs_index_mask) - 1]; 44379b8a705SPatrice Chotard 44479b8a705SPatrice Chotard dev_dbg(ospi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", 44579b8a705SPatrice Chotard op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, 44679b8a705SPatrice Chotard op->dummy.buswidth, op->data.buswidth, 44779b8a705SPatrice Chotard op->addr.val, op->data.nbytes); 44879b8a705SPatrice Chotard 44979b8a705SPatrice Chotard cr = readl_relaxed(ospi->regs_base + OSPI_CR); 45079b8a705SPatrice Chotard cr &= ~CR_CSSEL; 45179b8a705SPatrice Chotard cr |= FIELD_PREP(CR_CSSEL, cs); 45279b8a705SPatrice Chotard cr &= ~CR_FMODE_MASK; 45379b8a705SPatrice Chotard cr |= FIELD_PREP(CR_FMODE_MASK, ospi->fmode); 45479b8a705SPatrice Chotard writel_relaxed(cr, regs_base + OSPI_CR); 45579b8a705SPatrice Chotard 45679b8a705SPatrice Chotard if (op->data.nbytes) 45779b8a705SPatrice Chotard writel_relaxed(op->data.nbytes - 1, regs_base + OSPI_DLR); 45879b8a705SPatrice Chotard 45979b8a705SPatrice Chotard /* set prescaler */ 46079b8a705SPatrice Chotard dcr2 = readl_relaxed(regs_base + OSPI_DCR2); 46179b8a705SPatrice Chotard dcr2 |= FIELD_PREP(DCR2_PRESC_MASK, ospi->flash_presc[cs]); 46279b8a705SPatrice Chotard writel_relaxed(dcr2, regs_base + OSPI_DCR2); 46379b8a705SPatrice Chotard 46479b8a705SPatrice Chotard ccr = FIELD_PREP(CCR_IMODE_MASK, stm32_ospi_get_mode(op->cmd.buswidth)); 46579b8a705SPatrice Chotard 46679b8a705SPatrice Chotard if (op->addr.nbytes) { 46779b8a705SPatrice Chotard ccr |= FIELD_PREP(CCR_ADMODE_MASK, 46879b8a705SPatrice Chotard stm32_ospi_get_mode(op->addr.buswidth)); 46979b8a705SPatrice Chotard ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1); 47079b8a705SPatrice Chotard } 47179b8a705SPatrice Chotard 47279b8a705SPatrice Chotard tcr = TCR_SSHIFT; 47379b8a705SPatrice Chotard if (op->dummy.buswidth && op->dummy.nbytes) { 47479b8a705SPatrice Chotard tcr |= FIELD_PREP(TCR_DCYC_MASK, 47579b8a705SPatrice Chotard op->dummy.nbytes * 8 / op->dummy.buswidth); 47679b8a705SPatrice Chotard } 47779b8a705SPatrice Chotard writel_relaxed(tcr, regs_base + OSPI_TCR); 47879b8a705SPatrice Chotard 47979b8a705SPatrice Chotard if (op->data.nbytes) { 48079b8a705SPatrice Chotard ccr |= FIELD_PREP(CCR_DMODE_MASK, 48179b8a705SPatrice Chotard stm32_ospi_get_mode(op->data.buswidth)); 48279b8a705SPatrice Chotard } 48379b8a705SPatrice Chotard 48479b8a705SPatrice Chotard writel_relaxed(ccr, regs_base + OSPI_CCR); 48579b8a705SPatrice Chotard 48679b8a705SPatrice Chotard /* set instruction, must be set after ccr register update */ 48779b8a705SPatrice Chotard writel_relaxed(op->cmd.opcode, regs_base + OSPI_IR); 48879b8a705SPatrice Chotard 48979b8a705SPatrice Chotard if (op->addr.nbytes && ospi->fmode != CR_FMODE_MM) 49079b8a705SPatrice Chotard writel_relaxed(op->addr.val, regs_base + OSPI_AR); 49179b8a705SPatrice Chotard 49279b8a705SPatrice Chotard if (ospi->fmode == CR_FMODE_APM) 49379b8a705SPatrice Chotard err_poll_status = stm32_ospi_wait_poll_status(ospi, op); 49479b8a705SPatrice Chotard 49579b8a705SPatrice Chotard err = stm32_ospi_xfer(ospi, op); 49679b8a705SPatrice Chotard 49779b8a705SPatrice Chotard /* 49879b8a705SPatrice Chotard * Abort in: 49979b8a705SPatrice Chotard * -error case 50079b8a705SPatrice Chotard * -read memory map: prefetching must be stopped if we read the last 50179b8a705SPatrice Chotard * byte of device (device size - fifo size). like device size is not 50279b8a705SPatrice Chotard * knows, the prefetching is always stop. 50379b8a705SPatrice Chotard */ 50479b8a705SPatrice Chotard if (err || err_poll_status || ospi->fmode == CR_FMODE_MM) 50579b8a705SPatrice Chotard goto abort; 50679b8a705SPatrice Chotard 50779b8a705SPatrice Chotard /* Wait end of tx in indirect mode */ 50879b8a705SPatrice Chotard err = stm32_ospi_wait_cmd(ospi); 50979b8a705SPatrice Chotard if (err) 51079b8a705SPatrice Chotard goto abort; 51179b8a705SPatrice Chotard 51279b8a705SPatrice Chotard return 0; 51379b8a705SPatrice Chotard 51479b8a705SPatrice Chotard abort: 51579b8a705SPatrice Chotard timeout = stm32_ospi_abort(ospi); 51679b8a705SPatrice Chotard writel_relaxed(FCR_CTCF | FCR_CSMF, regs_base + OSPI_FCR); 51779b8a705SPatrice Chotard 51879b8a705SPatrice Chotard if (err || err_poll_status || timeout) 51979b8a705SPatrice Chotard dev_err(ospi->dev, "%s err:%d err_poll_status:%d abort timeout:%d\n", 52079b8a705SPatrice Chotard __func__, err, err_poll_status, timeout); 52179b8a705SPatrice Chotard 52279b8a705SPatrice Chotard return err; 52379b8a705SPatrice Chotard } 52479b8a705SPatrice Chotard 52579b8a705SPatrice Chotard static int stm32_ospi_poll_status(struct spi_mem *mem, 52679b8a705SPatrice Chotard const struct spi_mem_op *op, 52779b8a705SPatrice Chotard u16 mask, u16 match, 52879b8a705SPatrice Chotard unsigned long initial_delay_us, 52979b8a705SPatrice Chotard unsigned long polling_rate_us, 53079b8a705SPatrice Chotard unsigned long timeout_ms) 53179b8a705SPatrice Chotard { 53279b8a705SPatrice Chotard struct stm32_ospi *ospi = spi_controller_get_devdata(mem->spi->controller); 53379b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 53479b8a705SPatrice Chotard int ret; 53579b8a705SPatrice Chotard 53679b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 53779b8a705SPatrice Chotard if (ret < 0) 53879b8a705SPatrice Chotard return ret; 53979b8a705SPatrice Chotard 54079b8a705SPatrice Chotard mutex_lock(&ospi->lock); 54179b8a705SPatrice Chotard 54279b8a705SPatrice Chotard writel_relaxed(mask, regs_base + OSPI_PSMKR); 54379b8a705SPatrice Chotard writel_relaxed(match, regs_base + OSPI_PSMAR); 54479b8a705SPatrice Chotard ospi->fmode = CR_FMODE_APM; 54579b8a705SPatrice Chotard ospi->status_timeout = timeout_ms; 54679b8a705SPatrice Chotard 54779b8a705SPatrice Chotard ret = stm32_ospi_send(mem->spi, op); 54879b8a705SPatrice Chotard mutex_unlock(&ospi->lock); 54979b8a705SPatrice Chotard 55079b8a705SPatrice Chotard pm_runtime_mark_last_busy(ospi->dev); 55179b8a705SPatrice Chotard pm_runtime_put_autosuspend(ospi->dev); 55279b8a705SPatrice Chotard 55379b8a705SPatrice Chotard return ret; 55479b8a705SPatrice Chotard } 55579b8a705SPatrice Chotard 55679b8a705SPatrice Chotard static int stm32_ospi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) 55779b8a705SPatrice Chotard { 55879b8a705SPatrice Chotard struct stm32_ospi *ospi = spi_controller_get_devdata(mem->spi->controller); 55979b8a705SPatrice Chotard int ret; 56079b8a705SPatrice Chotard 56179b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 56279b8a705SPatrice Chotard if (ret < 0) 56379b8a705SPatrice Chotard return ret; 56479b8a705SPatrice Chotard 56579b8a705SPatrice Chotard mutex_lock(&ospi->lock); 56679b8a705SPatrice Chotard if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) 56779b8a705SPatrice Chotard ospi->fmode = CR_FMODE_INDR; 56879b8a705SPatrice Chotard else 56979b8a705SPatrice Chotard ospi->fmode = CR_FMODE_INDW; 57079b8a705SPatrice Chotard 57179b8a705SPatrice Chotard ret = stm32_ospi_send(mem->spi, op); 57279b8a705SPatrice Chotard mutex_unlock(&ospi->lock); 57379b8a705SPatrice Chotard 57479b8a705SPatrice Chotard pm_runtime_mark_last_busy(ospi->dev); 57579b8a705SPatrice Chotard pm_runtime_put_autosuspend(ospi->dev); 57679b8a705SPatrice Chotard 57779b8a705SPatrice Chotard return ret; 57879b8a705SPatrice Chotard } 57979b8a705SPatrice Chotard 58079b8a705SPatrice Chotard static int stm32_ospi_dirmap_create(struct spi_mem_dirmap_desc *desc) 58179b8a705SPatrice Chotard { 58279b8a705SPatrice Chotard struct stm32_ospi *ospi = spi_controller_get_devdata(desc->mem->spi->controller); 58379b8a705SPatrice Chotard 58479b8a705SPatrice Chotard if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) 58579b8a705SPatrice Chotard return -EOPNOTSUPP; 58679b8a705SPatrice Chotard 58779b8a705SPatrice Chotard /* Should never happen, as mm_base == null is an error probe exit condition */ 58879b8a705SPatrice Chotard if (!ospi->mm_base && desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) 58979b8a705SPatrice Chotard return -EOPNOTSUPP; 59079b8a705SPatrice Chotard 59179b8a705SPatrice Chotard if (!ospi->mm_size) 59279b8a705SPatrice Chotard return -EOPNOTSUPP; 59379b8a705SPatrice Chotard 59479b8a705SPatrice Chotard return 0; 59579b8a705SPatrice Chotard } 59679b8a705SPatrice Chotard 59779b8a705SPatrice Chotard static ssize_t stm32_ospi_dirmap_read(struct spi_mem_dirmap_desc *desc, 59879b8a705SPatrice Chotard u64 offs, size_t len, void *buf) 59979b8a705SPatrice Chotard { 60079b8a705SPatrice Chotard struct stm32_ospi *ospi = spi_controller_get_devdata(desc->mem->spi->controller); 60179b8a705SPatrice Chotard struct spi_mem_op op; 60279b8a705SPatrice Chotard u32 addr_max; 60379b8a705SPatrice Chotard int ret; 60479b8a705SPatrice Chotard 60579b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 60679b8a705SPatrice Chotard if (ret < 0) 60779b8a705SPatrice Chotard return ret; 60879b8a705SPatrice Chotard 60979b8a705SPatrice Chotard mutex_lock(&ospi->lock); 61079b8a705SPatrice Chotard /* 61179b8a705SPatrice Chotard * Make a local copy of desc op_tmpl and complete dirmap rdesc 61279b8a705SPatrice Chotard * spi_mem_op template with offs, len and *buf in order to get 61379b8a705SPatrice Chotard * all needed transfer information into struct spi_mem_op 61479b8a705SPatrice Chotard */ 61579b8a705SPatrice Chotard memcpy(&op, &desc->info.op_tmpl, sizeof(struct spi_mem_op)); 61679b8a705SPatrice Chotard dev_dbg(ospi->dev, "%s len = 0x%zx offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf); 61779b8a705SPatrice Chotard 61879b8a705SPatrice Chotard op.data.nbytes = len; 61979b8a705SPatrice Chotard op.addr.val = desc->info.offset + offs; 62079b8a705SPatrice Chotard op.data.buf.in = buf; 62179b8a705SPatrice Chotard 62279b8a705SPatrice Chotard addr_max = op.addr.val + op.data.nbytes + 1; 62379b8a705SPatrice Chotard if (addr_max < ospi->mm_size && op.addr.buswidth) 62479b8a705SPatrice Chotard ospi->fmode = CR_FMODE_MM; 62579b8a705SPatrice Chotard else 62679b8a705SPatrice Chotard ospi->fmode = CR_FMODE_INDR; 62779b8a705SPatrice Chotard 62879b8a705SPatrice Chotard ret = stm32_ospi_send(desc->mem->spi, &op); 62979b8a705SPatrice Chotard mutex_unlock(&ospi->lock); 63079b8a705SPatrice Chotard 63179b8a705SPatrice Chotard pm_runtime_mark_last_busy(ospi->dev); 63279b8a705SPatrice Chotard pm_runtime_put_autosuspend(ospi->dev); 63379b8a705SPatrice Chotard 63479b8a705SPatrice Chotard return ret ?: len; 63579b8a705SPatrice Chotard } 63679b8a705SPatrice Chotard 63779b8a705SPatrice Chotard static int stm32_ospi_transfer_one_message(struct spi_controller *ctrl, 63879b8a705SPatrice Chotard struct spi_message *msg) 63979b8a705SPatrice Chotard { 64079b8a705SPatrice Chotard struct stm32_ospi *ospi = spi_controller_get_devdata(ctrl); 64179b8a705SPatrice Chotard struct spi_transfer *transfer; 64279b8a705SPatrice Chotard struct spi_device *spi = msg->spi; 64379b8a705SPatrice Chotard struct spi_mem_op op; 64479b8a705SPatrice Chotard struct gpio_desc *cs_gpiod = spi->cs_gpiod[ffs(spi->cs_index_mask) - 1]; 64579b8a705SPatrice Chotard int ret = 0; 64679b8a705SPatrice Chotard 64779b8a705SPatrice Chotard if (!cs_gpiod) 64879b8a705SPatrice Chotard return -EOPNOTSUPP; 64979b8a705SPatrice Chotard 65079b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 65179b8a705SPatrice Chotard if (ret < 0) 65279b8a705SPatrice Chotard return ret; 65379b8a705SPatrice Chotard 65479b8a705SPatrice Chotard mutex_lock(&ospi->lock); 65579b8a705SPatrice Chotard 65679b8a705SPatrice Chotard gpiod_set_value_cansleep(cs_gpiod, true); 65779b8a705SPatrice Chotard 65879b8a705SPatrice Chotard list_for_each_entry(transfer, &msg->transfers, transfer_list) { 65979b8a705SPatrice Chotard u8 dummy_bytes = 0; 66079b8a705SPatrice Chotard 66179b8a705SPatrice Chotard memset(&op, 0, sizeof(op)); 66279b8a705SPatrice Chotard 66379b8a705SPatrice Chotard dev_dbg(ospi->dev, "tx_buf:%p tx_nbits:%d rx_buf:%p rx_nbits:%d len:%d dummy_data:%d\n", 66479b8a705SPatrice Chotard transfer->tx_buf, transfer->tx_nbits, 66579b8a705SPatrice Chotard transfer->rx_buf, transfer->rx_nbits, 66679b8a705SPatrice Chotard transfer->len, transfer->dummy_data); 66779b8a705SPatrice Chotard 66879b8a705SPatrice Chotard /* 66979b8a705SPatrice Chotard * OSPI hardware supports dummy bytes transfer. 67079b8a705SPatrice Chotard * If current transfer is dummy byte, merge it with the next 67179b8a705SPatrice Chotard * transfer in order to take into account OSPI block constraint 67279b8a705SPatrice Chotard */ 67379b8a705SPatrice Chotard if (transfer->dummy_data) { 67479b8a705SPatrice Chotard op.dummy.buswidth = transfer->tx_nbits; 67579b8a705SPatrice Chotard op.dummy.nbytes = transfer->len; 67679b8a705SPatrice Chotard dummy_bytes = transfer->len; 67779b8a705SPatrice Chotard 67879b8a705SPatrice Chotard /* If happens, means that message is not correctly built */ 67979b8a705SPatrice Chotard if (list_is_last(&transfer->transfer_list, &msg->transfers)) { 68079b8a705SPatrice Chotard ret = -EINVAL; 68179b8a705SPatrice Chotard goto end_of_transfer; 68279b8a705SPatrice Chotard } 68379b8a705SPatrice Chotard 68479b8a705SPatrice Chotard transfer = list_next_entry(transfer, transfer_list); 68579b8a705SPatrice Chotard } 68679b8a705SPatrice Chotard 68779b8a705SPatrice Chotard op.data.nbytes = transfer->len; 68879b8a705SPatrice Chotard 68979b8a705SPatrice Chotard if (transfer->rx_buf) { 69079b8a705SPatrice Chotard ospi->fmode = CR_FMODE_INDR; 69179b8a705SPatrice Chotard op.data.buswidth = transfer->rx_nbits; 69279b8a705SPatrice Chotard op.data.dir = SPI_MEM_DATA_IN; 69379b8a705SPatrice Chotard op.data.buf.in = transfer->rx_buf; 69479b8a705SPatrice Chotard } else { 69579b8a705SPatrice Chotard ospi->fmode = CR_FMODE_INDW; 69679b8a705SPatrice Chotard op.data.buswidth = transfer->tx_nbits; 69779b8a705SPatrice Chotard op.data.dir = SPI_MEM_DATA_OUT; 69879b8a705SPatrice Chotard op.data.buf.out = transfer->tx_buf; 69979b8a705SPatrice Chotard } 70079b8a705SPatrice Chotard 70179b8a705SPatrice Chotard ret = stm32_ospi_send(spi, &op); 70279b8a705SPatrice Chotard if (ret) 70379b8a705SPatrice Chotard goto end_of_transfer; 70479b8a705SPatrice Chotard 70579b8a705SPatrice Chotard msg->actual_length += transfer->len + dummy_bytes; 70679b8a705SPatrice Chotard } 70779b8a705SPatrice Chotard 70879b8a705SPatrice Chotard end_of_transfer: 70979b8a705SPatrice Chotard gpiod_set_value_cansleep(cs_gpiod, false); 71079b8a705SPatrice Chotard 71179b8a705SPatrice Chotard mutex_unlock(&ospi->lock); 71279b8a705SPatrice Chotard 71379b8a705SPatrice Chotard msg->status = ret; 71479b8a705SPatrice Chotard spi_finalize_current_message(ctrl); 71579b8a705SPatrice Chotard 71679b8a705SPatrice Chotard pm_runtime_mark_last_busy(ospi->dev); 71779b8a705SPatrice Chotard pm_runtime_put_autosuspend(ospi->dev); 71879b8a705SPatrice Chotard 71979b8a705SPatrice Chotard return ret; 72079b8a705SPatrice Chotard } 72179b8a705SPatrice Chotard 72279b8a705SPatrice Chotard static int stm32_ospi_setup(struct spi_device *spi) 72379b8a705SPatrice Chotard { 72479b8a705SPatrice Chotard struct spi_controller *ctrl = spi->controller; 72579b8a705SPatrice Chotard struct stm32_ospi *ospi = spi_controller_get_devdata(ctrl); 72679b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 72779b8a705SPatrice Chotard int ret; 72879b8a705SPatrice Chotard u8 cs = spi->chip_select[ffs(spi->cs_index_mask) - 1]; 72979b8a705SPatrice Chotard 73079b8a705SPatrice Chotard if (ctrl->busy) 73179b8a705SPatrice Chotard return -EBUSY; 73279b8a705SPatrice Chotard 73379b8a705SPatrice Chotard if (!spi->max_speed_hz) 73479b8a705SPatrice Chotard return -EINVAL; 73579b8a705SPatrice Chotard 73679b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 73779b8a705SPatrice Chotard if (ret < 0) 73879b8a705SPatrice Chotard return ret; 73979b8a705SPatrice Chotard 74079b8a705SPatrice Chotard ospi->flash_presc[cs] = DIV_ROUND_UP(ospi->clk_rate, spi->max_speed_hz) - 1; 74179b8a705SPatrice Chotard 74279b8a705SPatrice Chotard mutex_lock(&ospi->lock); 74379b8a705SPatrice Chotard 74479b8a705SPatrice Chotard ospi->cr_reg = CR_APMS | 3 << CR_FTHRES_SHIFT | CR_EN; 74579b8a705SPatrice Chotard writel_relaxed(ospi->cr_reg, regs_base + OSPI_CR); 74679b8a705SPatrice Chotard 74779b8a705SPatrice Chotard /* set dcr fsize to max address */ 74879b8a705SPatrice Chotard ospi->dcr_reg = DCR1_DEVSIZE_MASK | DCR1_DLYBYP; 74979b8a705SPatrice Chotard writel_relaxed(ospi->dcr_reg, regs_base + OSPI_DCR1); 75079b8a705SPatrice Chotard 75179b8a705SPatrice Chotard mutex_unlock(&ospi->lock); 75279b8a705SPatrice Chotard 75379b8a705SPatrice Chotard pm_runtime_mark_last_busy(ospi->dev); 75479b8a705SPatrice Chotard pm_runtime_put_autosuspend(ospi->dev); 75579b8a705SPatrice Chotard 75679b8a705SPatrice Chotard return 0; 75779b8a705SPatrice Chotard } 75879b8a705SPatrice Chotard 75979b8a705SPatrice Chotard /* 76079b8a705SPatrice Chotard * No special host constraint, so use default spi_mem_default_supports_op 76179b8a705SPatrice Chotard * to check supported mode. 76279b8a705SPatrice Chotard */ 76379b8a705SPatrice Chotard static const struct spi_controller_mem_ops stm32_ospi_mem_ops = { 76479b8a705SPatrice Chotard .exec_op = stm32_ospi_exec_op, 76579b8a705SPatrice Chotard .dirmap_create = stm32_ospi_dirmap_create, 76679b8a705SPatrice Chotard .dirmap_read = stm32_ospi_dirmap_read, 76779b8a705SPatrice Chotard .poll_status = stm32_ospi_poll_status, 76879b8a705SPatrice Chotard }; 76979b8a705SPatrice Chotard 77079b8a705SPatrice Chotard static int stm32_ospi_get_resources(struct platform_device *pdev) 77179b8a705SPatrice Chotard { 77279b8a705SPatrice Chotard struct device *dev = &pdev->dev; 77379b8a705SPatrice Chotard struct stm32_ospi *ospi = platform_get_drvdata(pdev); 77479b8a705SPatrice Chotard struct resource *res; 77579b8a705SPatrice Chotard struct reserved_mem *rmem = NULL; 77679b8a705SPatrice Chotard struct device_node *node; 77779b8a705SPatrice Chotard int ret; 77879b8a705SPatrice Chotard 77979b8a705SPatrice Chotard ospi->regs_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 78079b8a705SPatrice Chotard if (IS_ERR(ospi->regs_base)) 78179b8a705SPatrice Chotard return PTR_ERR(ospi->regs_base); 78279b8a705SPatrice Chotard 78379b8a705SPatrice Chotard ospi->regs_phys_base = res->start; 78479b8a705SPatrice Chotard 78579b8a705SPatrice Chotard ospi->clk = devm_clk_get(dev, NULL); 78679b8a705SPatrice Chotard if (IS_ERR(ospi->clk)) 78779b8a705SPatrice Chotard return dev_err_probe(dev, PTR_ERR(ospi->clk), 78879b8a705SPatrice Chotard "Can't get clock\n"); 78979b8a705SPatrice Chotard 79079b8a705SPatrice Chotard ospi->clk_rate = clk_get_rate(ospi->clk); 79179b8a705SPatrice Chotard if (!ospi->clk_rate) { 79279b8a705SPatrice Chotard dev_err(dev, "Invalid clock rate\n"); 79379b8a705SPatrice Chotard return -EINVAL; 79479b8a705SPatrice Chotard } 79579b8a705SPatrice Chotard 79679b8a705SPatrice Chotard ospi->irq = platform_get_irq(pdev, 0); 7973707fd9cSJiapeng Chong if (ospi->irq < 0) 79879b8a705SPatrice Chotard return ospi->irq; 79979b8a705SPatrice Chotard 80079b8a705SPatrice Chotard ret = devm_request_irq(dev, ospi->irq, stm32_ospi_irq, 0, 80179b8a705SPatrice Chotard dev_name(dev), ospi); 80279b8a705SPatrice Chotard if (ret) { 80379b8a705SPatrice Chotard dev_err(dev, "Failed to request irq\n"); 80479b8a705SPatrice Chotard return ret; 80579b8a705SPatrice Chotard } 80679b8a705SPatrice Chotard 80779b8a705SPatrice Chotard ospi->rstc = devm_reset_control_array_get_optional_exclusive(dev); 80879b8a705SPatrice Chotard if (IS_ERR(ospi->rstc)) 80979b8a705SPatrice Chotard return dev_err_probe(dev, PTR_ERR(ospi->rstc), 81079b8a705SPatrice Chotard "Can't get reset\n"); 81179b8a705SPatrice Chotard 81279b8a705SPatrice Chotard ospi->dma_chrx = dma_request_chan(dev, "rx"); 81379b8a705SPatrice Chotard if (IS_ERR(ospi->dma_chrx)) { 81479b8a705SPatrice Chotard ret = PTR_ERR(ospi->dma_chrx); 81579b8a705SPatrice Chotard ospi->dma_chrx = NULL; 81679b8a705SPatrice Chotard if (ret == -EPROBE_DEFER) 81779b8a705SPatrice Chotard goto err_dma; 81879b8a705SPatrice Chotard } 81979b8a705SPatrice Chotard 82079b8a705SPatrice Chotard ospi->dma_chtx = dma_request_chan(dev, "tx"); 82179b8a705SPatrice Chotard if (IS_ERR(ospi->dma_chtx)) { 82279b8a705SPatrice Chotard ret = PTR_ERR(ospi->dma_chtx); 82379b8a705SPatrice Chotard ospi->dma_chtx = NULL; 82479b8a705SPatrice Chotard if (ret == -EPROBE_DEFER) 82579b8a705SPatrice Chotard goto err_dma; 82679b8a705SPatrice Chotard } 82779b8a705SPatrice Chotard 82879b8a705SPatrice Chotard node = of_parse_phandle(dev->of_node, "memory-region", 0); 82979b8a705SPatrice Chotard if (node) 83079b8a705SPatrice Chotard rmem = of_reserved_mem_lookup(node); 83179b8a705SPatrice Chotard of_node_put(node); 83279b8a705SPatrice Chotard 83379b8a705SPatrice Chotard if (rmem) { 83479b8a705SPatrice Chotard ospi->mm_size = rmem->size; 83579b8a705SPatrice Chotard ospi->mm_base = devm_ioremap(dev, rmem->base, rmem->size); 8367dfc9bddSDan Carpenter if (!ospi->mm_base) { 83779b8a705SPatrice Chotard dev_err(dev, "unable to map memory region: %pa+%pa\n", 83879b8a705SPatrice Chotard &rmem->base, &rmem->size); 8397dfc9bddSDan Carpenter ret = -ENOMEM; 84079b8a705SPatrice Chotard goto err_dma; 84179b8a705SPatrice Chotard } 84279b8a705SPatrice Chotard 84379b8a705SPatrice Chotard if (ospi->mm_size > STM32_OSPI_MAX_MMAP_SZ) { 84479b8a705SPatrice Chotard dev_err(dev, "Memory map size outsize bounds\n"); 84579b8a705SPatrice Chotard ret = -EINVAL; 84679b8a705SPatrice Chotard goto err_dma; 84779b8a705SPatrice Chotard } 84879b8a705SPatrice Chotard } else { 84979b8a705SPatrice Chotard dev_info(dev, "No memory-map region found\n"); 85079b8a705SPatrice Chotard } 85179b8a705SPatrice Chotard 85279b8a705SPatrice Chotard init_completion(&ospi->data_completion); 85379b8a705SPatrice Chotard init_completion(&ospi->match_completion); 85479b8a705SPatrice Chotard 85579b8a705SPatrice Chotard return 0; 85679b8a705SPatrice Chotard 85779b8a705SPatrice Chotard err_dma: 85879b8a705SPatrice Chotard dev_info(dev, "Can't get all resources (%d)\n", ret); 85979b8a705SPatrice Chotard 86079b8a705SPatrice Chotard if (ospi->dma_chtx) 86179b8a705SPatrice Chotard dma_release_channel(ospi->dma_chtx); 86279b8a705SPatrice Chotard if (ospi->dma_chrx) 86379b8a705SPatrice Chotard dma_release_channel(ospi->dma_chrx); 86479b8a705SPatrice Chotard 86579b8a705SPatrice Chotard return ret; 86679b8a705SPatrice Chotard }; 86779b8a705SPatrice Chotard 86879b8a705SPatrice Chotard static int stm32_ospi_probe(struct platform_device *pdev) 86979b8a705SPatrice Chotard { 87079b8a705SPatrice Chotard struct device *dev = &pdev->dev; 87179b8a705SPatrice Chotard struct spi_controller *ctrl; 87279b8a705SPatrice Chotard struct stm32_ospi *ospi; 87379b8a705SPatrice Chotard struct dma_slave_config dma_cfg; 87479b8a705SPatrice Chotard struct device_node *child; 87579b8a705SPatrice Chotard int ret; 87679b8a705SPatrice Chotard u8 spi_flash_count = 0; 87779b8a705SPatrice Chotard 87879b8a705SPatrice Chotard /* 87979b8a705SPatrice Chotard * Flash subnodes sanity check: 88079b8a705SPatrice Chotard * 1 or 2 spi-nand/spi-nor flashes => supported 88179b8a705SPatrice Chotard * All other flash node configuration => not supported 88279b8a705SPatrice Chotard */ 88379b8a705SPatrice Chotard for_each_available_child_of_node(dev->of_node, child) { 88479b8a705SPatrice Chotard if (of_device_is_compatible(child, "jedec,spi-nor") || 88579b8a705SPatrice Chotard of_device_is_compatible(child, "spi-nand")) 88679b8a705SPatrice Chotard spi_flash_count++; 88779b8a705SPatrice Chotard } 88879b8a705SPatrice Chotard 88979b8a705SPatrice Chotard if (spi_flash_count == 0 || spi_flash_count > 2) { 89079b8a705SPatrice Chotard dev_err(dev, "Incorrect DT flash node\n"); 89179b8a705SPatrice Chotard return -ENODEV; 89279b8a705SPatrice Chotard } 89379b8a705SPatrice Chotard 89479b8a705SPatrice Chotard ctrl = devm_spi_alloc_host(dev, sizeof(*ospi)); 89579b8a705SPatrice Chotard if (!ctrl) 89679b8a705SPatrice Chotard return -ENOMEM; 89779b8a705SPatrice Chotard 89879b8a705SPatrice Chotard ospi = spi_controller_get_devdata(ctrl); 89979b8a705SPatrice Chotard ospi->ctrl = ctrl; 90079b8a705SPatrice Chotard 90179b8a705SPatrice Chotard ospi->dev = &pdev->dev; 90279b8a705SPatrice Chotard platform_set_drvdata(pdev, ospi); 90379b8a705SPatrice Chotard 90479b8a705SPatrice Chotard ret = stm32_ospi_get_resources(pdev); 90579b8a705SPatrice Chotard if (ret) 90679b8a705SPatrice Chotard return ret; 90779b8a705SPatrice Chotard 90879b8a705SPatrice Chotard memset(&dma_cfg, 0, sizeof(dma_cfg)); 90979b8a705SPatrice Chotard dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 91079b8a705SPatrice Chotard dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 91179b8a705SPatrice Chotard dma_cfg.src_addr = ospi->regs_phys_base + OSPI_DR; 91279b8a705SPatrice Chotard dma_cfg.dst_addr = ospi->regs_phys_base + OSPI_DR; 91379b8a705SPatrice Chotard dma_cfg.src_maxburst = 4; 91479b8a705SPatrice Chotard dma_cfg.dst_maxburst = 4; 91579b8a705SPatrice Chotard stm32_ospi_dma_setup(ospi, &dma_cfg); 91679b8a705SPatrice Chotard 91779b8a705SPatrice Chotard mutex_init(&ospi->lock); 91879b8a705SPatrice Chotard 91979b8a705SPatrice Chotard ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | 92079b8a705SPatrice Chotard SPI_TX_DUAL | SPI_TX_QUAD | 92179b8a705SPatrice Chotard SPI_TX_OCTAL | SPI_RX_OCTAL; 92279b8a705SPatrice Chotard ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX; 92379b8a705SPatrice Chotard ctrl->setup = stm32_ospi_setup; 92479b8a705SPatrice Chotard ctrl->bus_num = -1; 92579b8a705SPatrice Chotard ctrl->mem_ops = &stm32_ospi_mem_ops; 92679b8a705SPatrice Chotard ctrl->use_gpio_descriptors = true; 92779b8a705SPatrice Chotard ctrl->transfer_one_message = stm32_ospi_transfer_one_message; 92879b8a705SPatrice Chotard ctrl->num_chipselect = STM32_OSPI_MAX_NORCHIP; 92979b8a705SPatrice Chotard ctrl->dev.of_node = dev->of_node; 93079b8a705SPatrice Chotard 93179b8a705SPatrice Chotard pm_runtime_enable(ospi->dev); 93279b8a705SPatrice Chotard pm_runtime_set_autosuspend_delay(ospi->dev, STM32_AUTOSUSPEND_DELAY); 93379b8a705SPatrice Chotard pm_runtime_use_autosuspend(ospi->dev); 93479b8a705SPatrice Chotard 93579b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 93679b8a705SPatrice Chotard if (ret < 0) 93779b8a705SPatrice Chotard goto err_pm_enable; 93879b8a705SPatrice Chotard 93979b8a705SPatrice Chotard if (ospi->rstc) { 94079b8a705SPatrice Chotard reset_control_assert(ospi->rstc); 94179b8a705SPatrice Chotard udelay(2); 94279b8a705SPatrice Chotard reset_control_deassert(ospi->rstc); 94379b8a705SPatrice Chotard } 94479b8a705SPatrice Chotard 94579b8a705SPatrice Chotard ret = spi_register_controller(ctrl); 94679b8a705SPatrice Chotard if (ret) { 94779b8a705SPatrice Chotard /* Disable ospi */ 94879b8a705SPatrice Chotard writel_relaxed(0, ospi->regs_base + OSPI_CR); 94979b8a705SPatrice Chotard goto err_pm_resume; 95079b8a705SPatrice Chotard } 95179b8a705SPatrice Chotard 95279b8a705SPatrice Chotard pm_runtime_mark_last_busy(ospi->dev); 95379b8a705SPatrice Chotard pm_runtime_put_autosuspend(ospi->dev); 95479b8a705SPatrice Chotard 95579b8a705SPatrice Chotard return 0; 95679b8a705SPatrice Chotard 95779b8a705SPatrice Chotard err_pm_resume: 95879b8a705SPatrice Chotard pm_runtime_put_sync_suspend(ospi->dev); 95979b8a705SPatrice Chotard 96079b8a705SPatrice Chotard err_pm_enable: 96179b8a705SPatrice Chotard pm_runtime_force_suspend(ospi->dev); 96279b8a705SPatrice Chotard mutex_destroy(&ospi->lock); 96379b8a705SPatrice Chotard 96479b8a705SPatrice Chotard return ret; 96579b8a705SPatrice Chotard } 96679b8a705SPatrice Chotard 96779b8a705SPatrice Chotard static void stm32_ospi_remove(struct platform_device *pdev) 96879b8a705SPatrice Chotard { 96979b8a705SPatrice Chotard struct stm32_ospi *ospi = platform_get_drvdata(pdev); 97079b8a705SPatrice Chotard int ret; 97179b8a705SPatrice Chotard 97279b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 97379b8a705SPatrice Chotard if (ret < 0) 97479b8a705SPatrice Chotard return; 97579b8a705SPatrice Chotard 97679b8a705SPatrice Chotard spi_unregister_controller(ospi->ctrl); 97779b8a705SPatrice Chotard /* Disable ospi */ 97879b8a705SPatrice Chotard writel_relaxed(0, ospi->regs_base + OSPI_CR); 97979b8a705SPatrice Chotard mutex_destroy(&ospi->lock); 98079b8a705SPatrice Chotard 98179b8a705SPatrice Chotard if (ospi->dma_chtx) 98279b8a705SPatrice Chotard dma_release_channel(ospi->dma_chtx); 98379b8a705SPatrice Chotard if (ospi->dma_chrx) 98479b8a705SPatrice Chotard dma_release_channel(ospi->dma_chrx); 98579b8a705SPatrice Chotard 98679b8a705SPatrice Chotard pm_runtime_put_sync_suspend(ospi->dev); 98779b8a705SPatrice Chotard pm_runtime_force_suspend(ospi->dev); 98879b8a705SPatrice Chotard } 98979b8a705SPatrice Chotard 99079b8a705SPatrice Chotard static int __maybe_unused stm32_ospi_suspend(struct device *dev) 99179b8a705SPatrice Chotard { 99279b8a705SPatrice Chotard struct stm32_ospi *ospi = dev_get_drvdata(dev); 99379b8a705SPatrice Chotard 99479b8a705SPatrice Chotard pinctrl_pm_select_sleep_state(dev); 99579b8a705SPatrice Chotard 99679b8a705SPatrice Chotard return pm_runtime_force_suspend(ospi->dev); 99779b8a705SPatrice Chotard } 99879b8a705SPatrice Chotard 99979b8a705SPatrice Chotard static int __maybe_unused stm32_ospi_resume(struct device *dev) 100079b8a705SPatrice Chotard { 100179b8a705SPatrice Chotard struct stm32_ospi *ospi = dev_get_drvdata(dev); 100279b8a705SPatrice Chotard void __iomem *regs_base = ospi->regs_base; 100379b8a705SPatrice Chotard int ret; 100479b8a705SPatrice Chotard 100579b8a705SPatrice Chotard ret = pm_runtime_force_resume(ospi->dev); 100679b8a705SPatrice Chotard if (ret < 0) 100779b8a705SPatrice Chotard return ret; 100879b8a705SPatrice Chotard 100979b8a705SPatrice Chotard pinctrl_pm_select_default_state(dev); 101079b8a705SPatrice Chotard 101179b8a705SPatrice Chotard ret = pm_runtime_resume_and_get(ospi->dev); 101279b8a705SPatrice Chotard if (ret < 0) 101379b8a705SPatrice Chotard return ret; 101479b8a705SPatrice Chotard 101579b8a705SPatrice Chotard writel_relaxed(ospi->cr_reg, regs_base + OSPI_CR); 101679b8a705SPatrice Chotard writel_relaxed(ospi->dcr_reg, regs_base + OSPI_DCR1); 101779b8a705SPatrice Chotard pm_runtime_mark_last_busy(ospi->dev); 101879b8a705SPatrice Chotard pm_runtime_put_autosuspend(ospi->dev); 101979b8a705SPatrice Chotard 102079b8a705SPatrice Chotard return 0; 102179b8a705SPatrice Chotard } 102279b8a705SPatrice Chotard 102379b8a705SPatrice Chotard static int __maybe_unused stm32_ospi_runtime_suspend(struct device *dev) 102479b8a705SPatrice Chotard { 102579b8a705SPatrice Chotard struct stm32_ospi *ospi = dev_get_drvdata(dev); 102679b8a705SPatrice Chotard 102779b8a705SPatrice Chotard clk_disable_unprepare(ospi->clk); 102879b8a705SPatrice Chotard 102979b8a705SPatrice Chotard return 0; 103079b8a705SPatrice Chotard } 103179b8a705SPatrice Chotard 103279b8a705SPatrice Chotard static int __maybe_unused stm32_ospi_runtime_resume(struct device *dev) 103379b8a705SPatrice Chotard { 103479b8a705SPatrice Chotard struct stm32_ospi *ospi = dev_get_drvdata(dev); 103579b8a705SPatrice Chotard 103679b8a705SPatrice Chotard return clk_prepare_enable(ospi->clk); 103779b8a705SPatrice Chotard } 103879b8a705SPatrice Chotard 103979b8a705SPatrice Chotard static const struct dev_pm_ops stm32_ospi_pm_ops = { 104079b8a705SPatrice Chotard SET_SYSTEM_SLEEP_PM_OPS(stm32_ospi_suspend, stm32_ospi_resume) 104179b8a705SPatrice Chotard SET_RUNTIME_PM_OPS(stm32_ospi_runtime_suspend, 104279b8a705SPatrice Chotard stm32_ospi_runtime_resume, NULL) 104379b8a705SPatrice Chotard }; 104479b8a705SPatrice Chotard 104579b8a705SPatrice Chotard static const struct of_device_id stm32_ospi_of_match[] = { 104679b8a705SPatrice Chotard { .compatible = "st,stm32mp25-ospi" }, 104779b8a705SPatrice Chotard {}, 104879b8a705SPatrice Chotard }; 104979b8a705SPatrice Chotard MODULE_DEVICE_TABLE(of, stm32_ospi_of_match); 105079b8a705SPatrice Chotard 105179b8a705SPatrice Chotard static struct platform_driver stm32_ospi_driver = { 105279b8a705SPatrice Chotard .probe = stm32_ospi_probe, 105379b8a705SPatrice Chotard .remove = stm32_ospi_remove, 105479b8a705SPatrice Chotard .driver = { 105579b8a705SPatrice Chotard .name = "stm32-ospi", 105679b8a705SPatrice Chotard .pm = &stm32_ospi_pm_ops, 105779b8a705SPatrice Chotard .of_match_table = stm32_ospi_of_match, 105879b8a705SPatrice Chotard }, 105979b8a705SPatrice Chotard }; 106079b8a705SPatrice Chotard module_platform_driver(stm32_ospi_driver); 106179b8a705SPatrice Chotard 106279b8a705SPatrice Chotard MODULE_DESCRIPTION("STMicroelectronics STM32 OCTO SPI driver"); 106379b8a705SPatrice Chotard MODULE_LICENSE("GPL"); 1064