diff options
Diffstat (limited to 'drivers/spi/spi-stm32-qspi.c')
| -rw-r--r-- | drivers/spi/spi-stm32-qspi.c | 262 |
1 files changed, 160 insertions, 102 deletions
diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 514337c86d2c..f2d19f1c5ab1 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -8,13 +8,13 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/errno.h> +#include <linux/gpio/consumer.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/platform_device.h> @@ -299,16 +299,13 @@ static int stm32_qspi_wait_nobusy(struct stm32_qspi *qspi) STM32_BUSY_TIMEOUT_US); } -static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi, - const struct spi_mem_op *op) +static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi) { u32 cr, sr; int err = 0; - if (!op->data.nbytes) - goto wait_nobusy; - - if (readl_relaxed(qspi->io_base + QSPI_SR) & SR_TCF) + if ((readl_relaxed(qspi->io_base + QSPI_SR) & SR_TCF) || + qspi->fmode == CCR_FMODE_APM) goto out; reinit_completion(&qspi->data_completion); @@ -327,15 +324,13 @@ static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi, out: /* clear flags */ writel_relaxed(FCR_CTCF | FCR_CTEF, qspi->io_base + QSPI_FCR); -wait_nobusy: if (!err) err = stm32_qspi_wait_nobusy(qspi); return err; } -static int stm32_qspi_wait_poll_status(struct stm32_qspi *qspi, - const struct spi_mem_op *op) +static int stm32_qspi_wait_poll_status(struct stm32_qspi *qspi) { u32 cr; @@ -352,30 +347,21 @@ static int stm32_qspi_wait_poll_status(struct stm32_qspi *qspi, return 0; } -static int stm32_qspi_get_mode(struct stm32_qspi *qspi, u8 buswidth) +static int stm32_qspi_get_mode(u8 buswidth) { - if (buswidth == 4) + if (buswidth >= 4) return CCR_BUSWIDTH_4; return buswidth; } -static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) +static int stm32_qspi_send(struct spi_device *spi, const struct spi_mem_op *op) { - struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); - struct stm32_qspi_flash *flash = &qspi->flash[mem->spi->chip_select]; + struct stm32_qspi *qspi = spi_controller_get_devdata(spi->controller); + struct stm32_qspi_flash *flash = &qspi->flash[spi_get_chipselect(spi, 0)]; u32 ccr, cr; int timeout, err = 0, err_poll_status = 0; - dev_dbg(qspi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", - op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, - op->dummy.buswidth, op->data.buswidth, - op->addr.val, op->data.nbytes); - - err = stm32_qspi_wait_nobusy(qspi); - if (err) - goto abort; - cr = readl_relaxed(qspi->io_base + QSPI_CR); cr &= ~CR_PRESC_MASK & ~CR_FSEL; cr |= FIELD_PREP(CR_PRESC_MASK, flash->presc); @@ -389,11 +375,11 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) ccr = qspi->fmode; ccr |= FIELD_PREP(CCR_INST_MASK, op->cmd.opcode); ccr |= FIELD_PREP(CCR_IMODE_MASK, - stm32_qspi_get_mode(qspi, op->cmd.buswidth)); + stm32_qspi_get_mode(op->cmd.buswidth)); if (op->addr.nbytes) { ccr |= FIELD_PREP(CCR_ADMODE_MASK, - stm32_qspi_get_mode(qspi, op->addr.buswidth)); + stm32_qspi_get_mode(op->addr.buswidth)); ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1); } @@ -403,7 +389,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) if (op->data.nbytes) { ccr |= FIELD_PREP(CCR_DMODE_MASK, - stm32_qspi_get_mode(qspi, op->data.buswidth)); + stm32_qspi_get_mode(op->data.buswidth)); } writel_relaxed(ccr, qspi->io_base + QSPI_CCR); @@ -412,7 +398,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) writel_relaxed(op->addr.val, qspi->io_base + QSPI_AR); if (qspi->fmode == CCR_FMODE_APM) - err_poll_status = stm32_qspi_wait_poll_status(qspi, op); + err_poll_status = stm32_qspi_wait_poll_status(qspi); err = stm32_qspi_tx(qspi, op); @@ -427,7 +413,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) goto abort; /* wait end of tx in indirect mode */ - err = stm32_qspi_wait_cmd(qspi, op); + err = stm32_qspi_wait_cmd(qspi); if (err) goto abort; @@ -457,17 +443,15 @@ static int stm32_qspi_poll_status(struct spi_mem *mem, const struct spi_mem_op * unsigned long polling_rate_us, unsigned long timeout_ms) { - struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); + struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->controller); int ret; if (!spi_mem_supports_op(mem, op)) return -EOPNOTSUPP; - ret = pm_runtime_get_sync(qspi->dev); - if (ret < 0) { - pm_runtime_put_noidle(qspi->dev); + ret = pm_runtime_resume_and_get(qspi->dev); + if (ret < 0) return ret; - } mutex_lock(&qspi->lock); @@ -476,10 +460,9 @@ static int stm32_qspi_poll_status(struct spi_mem *mem, const struct spi_mem_op * qspi->fmode = CCR_FMODE_APM; qspi->status_timeout = timeout_ms; - ret = stm32_qspi_send(mem, op); + ret = stm32_qspi_send(mem->spi, op); mutex_unlock(&qspi->lock); - pm_runtime_mark_last_busy(qspi->dev); pm_runtime_put_autosuspend(qspi->dev); return ret; @@ -487,14 +470,12 @@ static int stm32_qspi_poll_status(struct spi_mem *mem, const struct spi_mem_op * static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); + struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->controller); int ret; - ret = pm_runtime_get_sync(qspi->dev); - if (ret < 0) { - pm_runtime_put_noidle(qspi->dev); + ret = pm_runtime_resume_and_get(qspi->dev); + if (ret < 0) return ret; - } mutex_lock(&qspi->lock); if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) @@ -502,10 +483,9 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) else qspi->fmode = CCR_FMODE_INDW; - ret = stm32_qspi_send(mem, op); + ret = stm32_qspi_send(mem->spi, op); mutex_unlock(&qspi->lock); - pm_runtime_mark_last_busy(qspi->dev); pm_runtime_put_autosuspend(qspi->dev); return ret; @@ -513,7 +493,7 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) static int stm32_qspi_dirmap_create(struct spi_mem_dirmap_desc *desc) { - struct stm32_qspi *qspi = spi_controller_get_devdata(desc->mem->spi->master); + struct stm32_qspi *qspi = spi_controller_get_devdata(desc->mem->spi->controller); if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) return -EOPNOTSUPP; @@ -531,16 +511,14 @@ static int stm32_qspi_dirmap_create(struct spi_mem_dirmap_desc *desc) static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, void *buf) { - struct stm32_qspi *qspi = spi_controller_get_devdata(desc->mem->spi->master); + struct stm32_qspi *qspi = spi_controller_get_devdata(desc->mem->spi->controller); struct spi_mem_op op; u32 addr_max; int ret; - ret = pm_runtime_get_sync(qspi->dev); - if (ret < 0) { - pm_runtime_put_noidle(qspi->dev); + ret = pm_runtime_resume_and_get(qspi->dev); + if (ret < 0) return ret; - } mutex_lock(&qspi->lock); /* make a local copy of desc op_tmpl and complete dirmap rdesc @@ -560,21 +538,103 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, else qspi->fmode = CCR_FMODE_INDR; - ret = stm32_qspi_send(desc->mem, &op); + ret = stm32_qspi_send(desc->mem->spi, &op); mutex_unlock(&qspi->lock); - pm_runtime_mark_last_busy(qspi->dev); pm_runtime_put_autosuspend(qspi->dev); return ret ?: len; } +static int stm32_qspi_transfer_one_message(struct spi_controller *ctrl, + struct spi_message *msg) +{ + struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl); + struct spi_transfer *transfer; + struct spi_device *spi = msg->spi; + struct spi_mem_op op; + int ret = 0; + + if (!spi_get_csgpiod(spi, 0)) + return -EOPNOTSUPP; + + ret = pm_runtime_resume_and_get(qspi->dev); + if (ret < 0) + return ret; + + mutex_lock(&qspi->lock); + + gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), true); + + list_for_each_entry(transfer, &msg->transfers, transfer_list) { + u8 dummy_bytes = 0; + + memset(&op, 0, sizeof(op)); + + dev_dbg(qspi->dev, "tx_buf:%p tx_nbits:%d rx_buf:%p rx_nbits:%d len:%d dummy_data:%d\n", + transfer->tx_buf, transfer->tx_nbits, + transfer->rx_buf, transfer->rx_nbits, + transfer->len, transfer->dummy_data); + + /* + * QSPI hardware supports dummy bytes transfer. + * If current transfer is dummy byte, merge it with the next + * transfer in order to take into account QSPI block constraint + */ + if (transfer->dummy_data) { + op.dummy.buswidth = transfer->tx_nbits; + op.dummy.nbytes = transfer->len; + dummy_bytes = transfer->len; + + /* if happens, means that message is not correctly built */ + if (list_is_last(&transfer->transfer_list, &msg->transfers)) { + ret = -EINVAL; + goto end_of_transfer; + } + + transfer = list_next_entry(transfer, transfer_list); + } + + op.data.nbytes = transfer->len; + + if (transfer->rx_buf) { + qspi->fmode = CCR_FMODE_INDR; + op.data.buswidth = transfer->rx_nbits; + op.data.dir = SPI_MEM_DATA_IN; + op.data.buf.in = transfer->rx_buf; + } else { + qspi->fmode = CCR_FMODE_INDW; + op.data.buswidth = transfer->tx_nbits; + op.data.dir = SPI_MEM_DATA_OUT; + op.data.buf.out = transfer->tx_buf; + } + + ret = stm32_qspi_send(spi, &op); + if (ret) + goto end_of_transfer; + + msg->actual_length += transfer->len + dummy_bytes; + } + +end_of_transfer: + gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), false); + + mutex_unlock(&qspi->lock); + + msg->status = ret; + spi_finalize_current_message(ctrl); + + pm_runtime_put_autosuspend(qspi->dev); + + return ret; +} + static int stm32_qspi_setup(struct spi_device *spi) { - struct spi_controller *ctrl = spi->master; + struct spi_controller *ctrl = spi->controller; struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl); struct stm32_qspi_flash *flash; - u32 presc; + u32 presc, mode; int ret; if (ctrl->busy) @@ -583,20 +643,36 @@ static int stm32_qspi_setup(struct spi_device *spi) if (!spi->max_speed_hz) return -EINVAL; - ret = pm_runtime_get_sync(qspi->dev); - if (ret < 0) { - pm_runtime_put_noidle(qspi->dev); - return ret; + mode = spi->mode & (SPI_TX_OCTAL | SPI_RX_OCTAL); + if (mode && gpiod_count(qspi->dev, "cs") == -ENOENT) { + dev_err(qspi->dev, "spi-rx-bus-width\\/spi-tx-bus-width\\/cs-gpios\n"); + dev_err(qspi->dev, "configuration not supported\n"); + + return -EINVAL; } + ret = pm_runtime_resume_and_get(qspi->dev); + if (ret < 0) + return ret; + presc = DIV_ROUND_UP(qspi->clk_rate, spi->max_speed_hz) - 1; - flash = &qspi->flash[spi->chip_select]; - flash->cs = spi->chip_select; + flash = &qspi->flash[spi_get_chipselect(spi, 0)]; + flash->cs = spi_get_chipselect(spi, 0); flash->presc = presc; mutex_lock(&qspi->lock); qspi->cr_reg = CR_APMS | 3 << CR_FTHRES_SHIFT | CR_SSHIFT | CR_EN; + + /* + * Dual flash mode is only enable in case SPI_TX_OCTAL or SPI_RX_OCTAL + * is set in spi->mode and "cs-gpios" properties is found in DT + */ + if (mode) { + qspi->cr_reg |= CR_DFM; + dev_dbg(qspi->dev, "Dual flash mode enable"); + } + writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); /* set dcr fsize to max address */ @@ -604,7 +680,6 @@ static int stm32_qspi_setup(struct spi_device *spi) writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); mutex_unlock(&qspi->lock); - pm_runtime_mark_last_busy(qspi->dev); pm_runtime_put_autosuspend(qspi->dev); return 0; @@ -688,7 +763,7 @@ static int stm32_qspi_probe(struct platform_device *pdev) struct resource *res; int ret, irq; - ctrl = spi_alloc_master(dev, sizeof(*qspi)); + ctrl = devm_spi_alloc_host(dev, sizeof(*qspi)); if (!ctrl) return -ENOMEM; @@ -697,58 +772,46 @@ static int stm32_qspi_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi"); qspi->io_base = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->io_base)) { - ret = PTR_ERR(qspi->io_base); - goto err_master_put; - } + if (IS_ERR(qspi->io_base)) + return PTR_ERR(qspi->io_base); qspi->phys_base = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm"); qspi->mm_base = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->mm_base)) { - ret = PTR_ERR(qspi->mm_base); - goto err_master_put; - } + if (IS_ERR(qspi->mm_base)) + return PTR_ERR(qspi->mm_base); qspi->mm_size = resource_size(res); - if (qspi->mm_size > STM32_QSPI_MAX_MMAP_SZ) { - ret = -EINVAL; - goto err_master_put; - } + if (qspi->mm_size > STM32_QSPI_MAX_MMAP_SZ) + return -EINVAL; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - goto err_master_put; - } + if (irq < 0) + return irq; ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0, dev_name(dev), qspi); if (ret) { dev_err(dev, "failed to request irq\n"); - goto err_master_put; + return ret; } init_completion(&qspi->data_completion); init_completion(&qspi->match_completion); qspi->clk = devm_clk_get(dev, NULL); - if (IS_ERR(qspi->clk)) { - ret = PTR_ERR(qspi->clk); - goto err_master_put; - } + if (IS_ERR(qspi->clk)) + return PTR_ERR(qspi->clk); qspi->clk_rate = clk_get_rate(qspi->clk); - if (!qspi->clk_rate) { - ret = -EINVAL; - goto err_master_put; - } + if (!qspi->clk_rate) + return -EINVAL; ret = clk_prepare_enable(qspi->clk); if (ret) { dev_err(dev, "can not enable the clock\n"); - goto err_master_put; + return ret; } rstc = devm_reset_control_get_exclusive(dev, NULL); @@ -770,11 +833,13 @@ static int stm32_qspi_probe(struct platform_device *pdev) mutex_init(&qspi->lock); - ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD - | SPI_TX_DUAL | SPI_TX_QUAD; + ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_OCTAL + | SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_OCTAL; ctrl->setup = stm32_qspi_setup; ctrl->bus_num = -1; ctrl->mem_ops = &stm32_qspi_mem_ops; + ctrl->use_gpio_descriptors = true; + ctrl->transfer_one_message = stm32_qspi_transfer_one_message; ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP; ctrl->dev.of_node = dev->of_node; @@ -784,11 +849,10 @@ static int stm32_qspi_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_get_noresume(dev); - ret = devm_spi_register_master(dev, ctrl); + ret = spi_register_controller(ctrl); if (ret) goto err_pm_runtime_free; - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return 0; @@ -806,17 +870,16 @@ err_dma_free: stm32_qspi_dma_free(qspi); err_clk_disable: clk_disable_unprepare(qspi->clk); -err_master_put: - spi_master_put(qspi->ctrl); return ret; } -static int stm32_qspi_remove(struct platform_device *pdev) +static void stm32_qspi_remove(struct platform_device *pdev) { struct stm32_qspi *qspi = platform_get_drvdata(pdev); pm_runtime_get_sync(qspi->dev); + spi_unregister_controller(qspi->ctrl); /* disable qspi */ writel_relaxed(0, qspi->io_base + QSPI_CR); stm32_qspi_dma_free(qspi); @@ -826,8 +889,6 @@ static int stm32_qspi_remove(struct platform_device *pdev) pm_runtime_set_suspended(qspi->dev); pm_runtime_dont_use_autosuspend(qspi->dev); clk_disable_unprepare(qspi->clk); - - return 0; } static int __maybe_unused stm32_qspi_runtime_suspend(struct device *dev) @@ -864,16 +925,13 @@ static int __maybe_unused stm32_qspi_resume(struct device *dev) pinctrl_pm_select_default_state(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) return ret; - } writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); writel_relaxed(qspi->dcr_reg, qspi->io_base + QSPI_DCR); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return 0; @@ -893,7 +951,7 @@ MODULE_DEVICE_TABLE(of, stm32_qspi_match); static struct platform_driver stm32_qspi_driver = { .probe = stm32_qspi_probe, - .remove = stm32_qspi_remove, + .remove = stm32_qspi_remove, .driver = { .name = "stm32-qspi", .of_match_table = stm32_qspi_match, |
