summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-cadence-quadspi.c33
-rw-r--r--drivers/spi/spi-fsl-lpspi.c47
-rw-r--r--drivers/spi/spi-microchip-core-qspi.c12
-rw-r--r--drivers/spi/spi-qpic-snand.c6
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);