diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-cadence-quadspi.c | 33 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-lpspi.c | 47 | ||||
-rw-r--r-- | drivers/spi/spi-microchip-core-qspi.c | 12 | ||||
-rw-r--r-- | drivers/spi/spi-qpic-snand.c | 6 |
4 files changed, 65 insertions, 33 deletions
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 177f9a33f3a2..9bf823348cd3 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -108,6 +108,8 @@ struct cqspi_st { bool is_jh7110; /* Flag for StarFive JH7110 SoC */ bool disable_stig_mode; + refcount_t refcount; + refcount_t inflight_ops; const struct cqspi_driver_platdata *ddata; }; @@ -735,6 +737,9 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata, u8 *rxbuf_end = rxbuf + n_rx; int ret = 0; + if (!refcount_read(&cqspi->refcount)) + return -ENODEV; + writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR); writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES); @@ -1071,6 +1076,9 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata, unsigned int write_bytes; int ret; + if (!refcount_read(&cqspi->refcount)) + return -ENODEV; + writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR); writel(remaining, reg_base + CQSPI_REG_INDIRECTWRBYTES); @@ -1461,12 +1469,26 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller); struct device *dev = &cqspi->pdev->dev; + if (refcount_read(&cqspi->inflight_ops) == 0) + return -ENODEV; + ret = pm_runtime_resume_and_get(dev); if (ret) { dev_err(&mem->spi->dev, "resume failed with %d\n", ret); return ret; } + if (!refcount_read(&cqspi->refcount)) + return -EBUSY; + + refcount_inc(&cqspi->inflight_ops); + + if (!refcount_read(&cqspi->refcount)) { + if (refcount_read(&cqspi->inflight_ops)) + refcount_dec(&cqspi->inflight_ops); + return -EBUSY; + } + ret = cqspi_mem_process(mem, op); pm_runtime_put_autosuspend(dev); @@ -1474,6 +1496,9 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) if (ret) dev_err(&mem->spi->dev, "operation failed with %d\n", ret); + if (refcount_read(&cqspi->inflight_ops) > 1) + refcount_dec(&cqspi->inflight_ops); + return ret; } @@ -1925,6 +1950,9 @@ static int cqspi_probe(struct platform_device *pdev) } } + refcount_set(&cqspi->refcount, 1); + refcount_set(&cqspi->inflight_ops, 1); + ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0, pdev->name, cqspi); if (ret) { @@ -1987,6 +2015,11 @@ static void cqspi_remove(struct platform_device *pdev) { struct cqspi_st *cqspi = platform_get_drvdata(pdev); + refcount_set(&cqspi->refcount, 0); + + if (!refcount_dec_and_test(&cqspi->inflight_ops)) + cqspi_wait_idle(cqspi); + spi_unregister_controller(cqspi->host); cqspi_controller_enable(cqspi, 0); diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 313e444a34f3..431439d4cdda 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -3,8 +3,9 @@ // Freescale i.MX7ULP LPSPI driver // // Copyright 2016 Freescale Semiconductor, Inc. -// Copyright 2018 NXP Semiconductors +// Copyright 2018, 2023, 2025 NXP +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/completion.h> #include <linux/delay.h> @@ -70,7 +71,7 @@ #define DER_TDDE BIT(0) #define CFGR1_PCSCFG BIT(27) #define CFGR1_PINCFG (BIT(24)|BIT(25)) -#define CFGR1_PCSPOL BIT(8) +#define CFGR1_PCSPOL_MASK GENMASK(11, 8) #define CFGR1_NOSTALL BIT(3) #define CFGR1_HOST BIT(0) #define FSR_TXCOUNT (0xFF) @@ -82,8 +83,11 @@ #define TCR_RXMSK BIT(19) #define TCR_TXMSK BIT(18) +#define SR_CLEAR_MASK GENMASK(13, 8) + struct fsl_lpspi_devtype_data { - u8 prescale_max; + u8 prescale_max : 3; /* 0 == no limit */ + bool query_hw_for_num_cs : 1; }; struct lpspi_config { @@ -129,20 +133,26 @@ struct fsl_lpspi_data { }; /* - * ERR051608 fixed or not: - * https://www.nxp.com/docs/en/errata/i.MX93_1P87f.pdf + * Devices with ERR051608 have a max TCR_PRESCALE value of 1, otherwise there is + * no prescale limit: https://www.nxp.com/docs/en/errata/i.MX93_1P87f.pdf */ -static struct fsl_lpspi_devtype_data imx93_lpspi_devtype_data = { +static const struct fsl_lpspi_devtype_data imx93_lpspi_devtype_data = { .prescale_max = 1, + .query_hw_for_num_cs = true, +}; + +static const struct fsl_lpspi_devtype_data imx7ulp_lpspi_devtype_data = { + /* All defaults */ }; -static struct fsl_lpspi_devtype_data imx7ulp_lpspi_devtype_data = { - .prescale_max = 7, +static const struct fsl_lpspi_devtype_data s32g_lpspi_devtype_data = { + .query_hw_for_num_cs = true, }; static const struct of_device_id fsl_lpspi_dt_ids[] = { { .compatible = "fsl,imx7ulp-spi", .data = &imx7ulp_lpspi_devtype_data,}, { .compatible = "fsl,imx93-spi", .data = &imx93_lpspi_devtype_data,}, + { .compatible = "nxp,s32g2-lpspi", .data = &s32g_lpspi_devtype_data,}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids); @@ -321,7 +331,7 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) int scldiv; perclk_rate = clk_get_rate(fsl_lpspi->clk_per); - prescale_max = fsl_lpspi->devtype_data->prescale_max; + prescale_max = fsl_lpspi->devtype_data->prescale_max ?: 7; if (!config.speed_hz) { dev_err(fsl_lpspi->dev, @@ -423,7 +433,9 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi) else temp = CFGR1_PINCFG; if (fsl_lpspi->config.mode & SPI_CS_HIGH) - temp |= CFGR1_PCSPOL; + temp |= FIELD_PREP(CFGR1_PCSPOL_MASK, + BIT(fsl_lpspi->config.chip_select)); + writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1); temp = readl(fsl_lpspi->base + IMX7ULP_CR); @@ -532,14 +544,13 @@ static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi) fsl_lpspi_intctrl(fsl_lpspi, 0); } - /* W1C for all flags in SR */ - temp = 0x3F << 8; - writel(temp, fsl_lpspi->base + IMX7ULP_SR); - /* Clear FIFO and disable module */ temp = CR_RRF | CR_RTF; writel(temp, fsl_lpspi->base + IMX7ULP_CR); + /* W1C for all flags in SR */ + writel(SR_CLEAR_MASK, fsl_lpspi->base + IMX7ULP_SR); + return 0; } @@ -730,12 +741,10 @@ static int fsl_lpspi_pio_transfer(struct spi_controller *controller, fsl_lpspi_write_tx_fifo(fsl_lpspi); ret = fsl_lpspi_wait_for_completion(controller); - if (ret) - return ret; fsl_lpspi_reset(fsl_lpspi); - return 0; + return ret; } static int fsl_lpspi_transfer_one(struct spi_controller *controller, @@ -785,7 +794,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) if (temp_SR & SR_MBF || readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_TXCOUNT) { writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); - fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); + fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE | (temp_IER & IER_TDIE)); return IRQ_HANDLED; } @@ -930,7 +939,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f); if (of_property_read_u32((&pdev->dev)->of_node, "num-cs", &num_cs)) { - if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx93-spi")) + if (devtype_data->query_hw_for_num_cs) num_cs = ((temp >> 16) & 0xf); else num_cs = 1; diff --git a/drivers/spi/spi-microchip-core-qspi.c b/drivers/spi/spi-microchip-core-qspi.c index d13a9b755c7f..8dc98b17f77b 100644 --- a/drivers/spi/spi-microchip-core-qspi.c +++ b/drivers/spi/spi-microchip-core-qspi.c @@ -531,10 +531,6 @@ error: static bool mchp_coreqspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct mchp_coreqspi *qspi = spi_controller_get_devdata(mem->spi->controller); - unsigned long clk_hz; - u32 baud_rate_val; - if (!spi_mem_default_supports_op(mem, op)) return false; @@ -557,14 +553,6 @@ static bool mchp_coreqspi_supports_op(struct spi_mem *mem, const struct spi_mem_ return false; } - clk_hz = clk_get_rate(qspi->clk); - if (!clk_hz) - return false; - - baud_rate_val = DIV_ROUND_UP(clk_hz, 2 * op->max_freq); - if (baud_rate_val > MAX_DIVIDER || baud_rate_val < MIN_DIVIDER) - return false; - return true; } diff --git a/drivers/spi/spi-qpic-snand.c b/drivers/spi/spi-qpic-snand.c index 0ceaad7dba3c..780abb967822 100644 --- a/drivers/spi/spi-qpic-snand.c +++ b/drivers/spi/spi-qpic-snand.c @@ -1615,11 +1615,13 @@ static int qcom_spi_probe(struct platform_device *pdev) ret = spi_register_controller(ctlr); if (ret) { dev_err(&pdev->dev, "spi_register_controller failed.\n"); - goto err_spi_init; + goto err_register_controller; } return 0; +err_register_controller: + nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); err_spi_init: qcom_nandc_unalloc(snandc); err_snand_alloc: @@ -1641,7 +1643,7 @@ static void qcom_spi_remove(struct platform_device *pdev) struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi_unregister_controller(ctlr); - + nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); qcom_nandc_unalloc(snandc); clk_disable_unprepare(snandc->aon_clk); |