mirror of https://github.com/torvalds/linux.git
spi: Fixes for v6.17
The largest batch of fixes here is a series of fixes for the Freescale LPSPI driver which James Clark pulled out of their BSP while looking at support for the NXP S32G version of the controller. The majority of this turned out to be bug fixes that affect existing systems with the actual S32G support being just a small quirk that would be unremarkable by itself, the whole series has had a good amount of testing and review and the individual patches are all pretty straightforward by themselves. We also have a few other driver specific fixes, including a relatively large but simple one for the Cadence QuadSPI driver. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmi7LmEACgkQJNaLcl1U h9AryAf8Df0+9Za/JDEfh1s8Ritm+0vbkrcSUPa0ZLRBVJP+upssBEEMwwLscrRI hommkOawazLfTisCil+dWwEjxoBQpXyTDs+TUkHNjUX8aYHuKIAWqLelBDTpGl1e ni3UynzuQ8QRDkQhWKQpV35Oi1DvfeHbux714mONw9bX4YCoZdMfsPv5eWYe2qqh J/Ukflvg1NrR/lrJDB/iQLzDfHbHiQDUEo5Dj22CqEvRIpQpQvoazTnA5eFyKoVd dKjSolY4UO8cQijaLBwzQvrvsvcWT/gZpQHjCgoVTwJO23H59ePtGTxpmZDEs1sm QyVqP/ieQq23jq15eKnhwBK6VpKLyQ== =/RyU -----END PGP SIGNATURE----- Merge tag 'spi-fix-v6.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi Pull spi fixes from Mark Brown: "The largest batch of fixes here is a series of fixes for the Freescale LPSPI driver which James Clark pulled out of their BSP while looking at support for the NXP S32G version of the controller. The majority of this turned out to be bug fixes that affect existing systems with the actual S32G support being just a small quirk that would be unremarkable by itself, the whole series has had a good amount of testing and review and the individual patches are all pretty straightforward by themselves. We also have a few other driver specific fixes, including a relatively large but simple one for the Cadence QuadSPI driver" * tag 'spi-fix-v6.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spi-qpic-snand: unregister ECC engine on probe error and device remove spi: cadence-quadspi: Implement refcount to handle unbind during busy spi: spi-fsl-lpspi: Add compatible for S32G spi: spi-fsl-lpspi: Parameterize reading num-cs from hardware spi: spi-fsl-lpspi: Treat prescale_max == 0 as no erratum spi: spi-fsl-lpspi: Constify devtype datas dt-bindings: lpspi: Document support for S32G spi: spi-fsl-lpspi: Clear status register after disabling the module spi: spi-fsl-lpspi: Reset FIFO and disable module on transfer abort spi: spi-fsl-lpspi: Set correct chip-select polarity bit spi: spi-fsl-lpspi: Fix transmissions when using CONT spi: microchip-core-qspi: stop checking viability of op->max_freq in supports_op callback
This commit is contained in:
commit
53b48f62f2
|
|
@ -20,6 +20,7 @@ properties:
|
|||
- enum:
|
||||
- fsl,imx7ulp-spi
|
||||
- fsl,imx8qxp-spi
|
||||
- nxp,s32g2-lpspi
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx8ulp-spi
|
||||
|
|
@ -27,6 +28,10 @@ properties:
|
|||
- fsl,imx94-spi
|
||||
- fsl,imx95-spi
|
||||
- const: fsl,imx7ulp-spi
|
||||
- items:
|
||||
- const: nxp,s32g3-lpspi
|
||||
- const: nxp,s32g2-lpspi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 struct fsl_lpspi_devtype_data imx7ulp_lpspi_devtype_data = {
|
||||
.prescale_max = 7,
|
||||
static const struct fsl_lpspi_devtype_data imx7ulp_lpspi_devtype_data = {
|
||||
/* All defaults */
|
||||
};
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -531,10 +531,6 @@ static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue