Commit c2a905a6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-fix-v6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi fixes from Mark Brown:
 "A small collection of fixes here, all driver specific and none of them
  too serious. For whatever reason runtime PM seems to have been causing
  a bunch of issues recently"

* tag 'spi-fix-v6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: pxa2xx: Move PM runtime handling to the glue drivers
  spi: pxa2xx: Do not override dev->platform_data on probe
  spi: spi-fsl-lpspi: limit PRESCALE bit in TCR register
  spi: spi-cadence-quadspi: Fix OSPI NOR failures during system resume
  spi: zynqmp-gqspi: Scale timeout by data size
parents 3d5f968a e17465f7
...@@ -2000,13 +2000,25 @@ static int cqspi_runtime_resume(struct device *dev) ...@@ -2000,13 +2000,25 @@ static int cqspi_runtime_resume(struct device *dev)
static int cqspi_suspend(struct device *dev) static int cqspi_suspend(struct device *dev)
{ {
struct cqspi_st *cqspi = dev_get_drvdata(dev); struct cqspi_st *cqspi = dev_get_drvdata(dev);
int ret;
return spi_controller_suspend(cqspi->host); ret = spi_controller_suspend(cqspi->host);
if (ret)
return ret;
return pm_runtime_force_suspend(dev);
} }
static int cqspi_resume(struct device *dev) static int cqspi_resume(struct device *dev)
{ {
struct cqspi_st *cqspi = dev_get_drvdata(dev); struct cqspi_st *cqspi = dev_get_drvdata(dev);
int ret;
ret = pm_runtime_force_resume(dev);
if (ret) {
dev_err(dev, "pm_runtime_force_resume failed on resume\n");
return ret;
}
return spi_controller_resume(cqspi->host); return spi_controller_resume(cqspi->host);
} }
......
...@@ -82,6 +82,10 @@ ...@@ -82,6 +82,10 @@
#define TCR_RXMSK BIT(19) #define TCR_RXMSK BIT(19)
#define TCR_TXMSK BIT(18) #define TCR_TXMSK BIT(18)
struct fsl_lpspi_devtype_data {
u8 prescale_max;
};
struct lpspi_config { struct lpspi_config {
u8 bpw; u8 bpw;
u8 chip_select; u8 chip_select;
...@@ -119,10 +123,25 @@ struct fsl_lpspi_data { ...@@ -119,10 +123,25 @@ struct fsl_lpspi_data {
bool usedma; bool usedma;
struct completion dma_rx_completion; struct completion dma_rx_completion;
struct completion dma_tx_completion; struct completion dma_tx_completion;
const struct fsl_lpspi_devtype_data *devtype_data;
};
/*
* ERR051608 fixed or not:
* https://www.nxp.com/docs/en/errata/i.MX93_1P87f.pdf
*/
static struct fsl_lpspi_devtype_data imx93_lpspi_devtype_data = {
.prescale_max = 1,
};
static struct fsl_lpspi_devtype_data imx7ulp_lpspi_devtype_data = {
.prescale_max = 8,
}; };
static const struct of_device_id fsl_lpspi_dt_ids[] = { static const struct of_device_id fsl_lpspi_dt_ids[] = {
{ .compatible = "fsl,imx7ulp-spi", }, { .compatible = "fsl,imx7ulp-spi", .data = &imx7ulp_lpspi_devtype_data,},
{ .compatible = "fsl,imx93-spi", .data = &imx93_lpspi_devtype_data,},
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids); MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids);
...@@ -297,9 +316,11 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) ...@@ -297,9 +316,11 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
{ {
struct lpspi_config config = fsl_lpspi->config; struct lpspi_config config = fsl_lpspi->config;
unsigned int perclk_rate, scldiv, div; unsigned int perclk_rate, scldiv, div;
u8 prescale_max;
u8 prescale; u8 prescale;
perclk_rate = clk_get_rate(fsl_lpspi->clk_per); perclk_rate = clk_get_rate(fsl_lpspi->clk_per);
prescale_max = fsl_lpspi->devtype_data->prescale_max;
if (!config.speed_hz) { if (!config.speed_hz) {
dev_err(fsl_lpspi->dev, dev_err(fsl_lpspi->dev,
...@@ -315,7 +336,7 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) ...@@ -315,7 +336,7 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
div = DIV_ROUND_UP(perclk_rate, config.speed_hz); div = DIV_ROUND_UP(perclk_rate, config.speed_hz);
for (prescale = 0; prescale < 8; prescale++) { for (prescale = 0; prescale < prescale_max; prescale++) {
scldiv = div / (1 << prescale) - 2; scldiv = div / (1 << prescale) - 2;
if (scldiv < 256) { if (scldiv < 256) {
fsl_lpspi->config.prescale = prescale; fsl_lpspi->config.prescale = prescale;
...@@ -822,6 +843,7 @@ static int fsl_lpspi_init_rpm(struct fsl_lpspi_data *fsl_lpspi) ...@@ -822,6 +843,7 @@ static int fsl_lpspi_init_rpm(struct fsl_lpspi_data *fsl_lpspi)
static int fsl_lpspi_probe(struct platform_device *pdev) static int fsl_lpspi_probe(struct platform_device *pdev)
{ {
const struct fsl_lpspi_devtype_data *devtype_data;
struct fsl_lpspi_data *fsl_lpspi; struct fsl_lpspi_data *fsl_lpspi;
struct spi_controller *controller; struct spi_controller *controller;
struct resource *res; struct resource *res;
...@@ -830,6 +852,10 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -830,6 +852,10 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
u32 temp; u32 temp;
bool is_target; bool is_target;
devtype_data = of_device_get_match_data(&pdev->dev);
if (!devtype_data)
return -ENODEV;
is_target = of_property_read_bool((&pdev->dev)->of_node, "spi-slave"); is_target = of_property_read_bool((&pdev->dev)->of_node, "spi-slave");
if (is_target) if (is_target)
controller = devm_spi_alloc_target(&pdev->dev, controller = devm_spi_alloc_target(&pdev->dev,
...@@ -848,6 +874,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -848,6 +874,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
fsl_lpspi->is_target = is_target; fsl_lpspi->is_target = is_target;
fsl_lpspi->is_only_cs1 = of_property_read_bool((&pdev->dev)->of_node, fsl_lpspi->is_only_cs1 = of_property_read_bool((&pdev->dev)->of_node,
"fsl,spi-only-use-cs1-sel"); "fsl,spi-only-use-cs1-sel");
fsl_lpspi->devtype_data = devtype_data;
init_completion(&fsl_lpspi->xfer_done); init_completion(&fsl_lpspi->xfer_done);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/sprintf.h> #include <linux/sprintf.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -297,11 +298,23 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev, ...@@ -297,11 +298,23 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
return ret; return ret;
ssp->irq = pci_irq_vector(dev, 0); ssp->irq = pci_irq_vector(dev, 0);
return pxa2xx_spi_probe(&dev->dev, ssp); ret = pxa2xx_spi_probe(&dev->dev, ssp, pdata);
if (ret)
return ret;
pm_runtime_set_autosuspend_delay(&dev->dev, 50);
pm_runtime_use_autosuspend(&dev->dev);
pm_runtime_put_autosuspend(&dev->dev);
pm_runtime_allow(&dev->dev);
return 0;
} }
static void pxa2xx_spi_pci_remove(struct pci_dev *dev) static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
{ {
pm_runtime_forbid(&dev->dev);
pm_runtime_get_noresume(&dev->dev);
pxa2xx_spi_remove(&dev->dev); pxa2xx_spi_remove(&dev->dev);
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -63,7 +64,7 @@ static struct ssp_device *pxa2xx_spi_ssp_request(struct platform_device *pdev) ...@@ -63,7 +64,7 @@ static struct ssp_device *pxa2xx_spi_ssp_request(struct platform_device *pdev)
ssp = pxa_ssp_request(pdev->id, pdev->name); ssp = pxa_ssp_request(pdev->id, pdev->name);
if (!ssp) if (!ssp)
return ssp; return NULL;
status = devm_add_action_or_reset(&pdev->dev, pxa2xx_spi_ssp_release, ssp); status = devm_add_action_or_reset(&pdev->dev, pxa2xx_spi_ssp_release, ssp);
if (status) if (status)
...@@ -142,14 +143,13 @@ static int pxa2xx_spi_platform_probe(struct platform_device *pdev) ...@@ -142,14 +143,13 @@ static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
struct pxa2xx_spi_controller *platform_info; struct pxa2xx_spi_controller *platform_info;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ssp_device *ssp; struct ssp_device *ssp;
int ret;
platform_info = dev_get_platdata(dev); platform_info = dev_get_platdata(dev);
if (!platform_info) { if (!platform_info) {
platform_info = pxa2xx_spi_init_pdata(pdev); platform_info = pxa2xx_spi_init_pdata(pdev);
if (IS_ERR(platform_info)) if (IS_ERR(platform_info))
return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n"); return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
dev->platform_data = platform_info;
} }
ssp = pxa2xx_spi_ssp_request(pdev); ssp = pxa2xx_spi_ssp_request(pdev);
...@@ -158,12 +158,28 @@ static int pxa2xx_spi_platform_probe(struct platform_device *pdev) ...@@ -158,12 +158,28 @@ static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
if (!ssp) if (!ssp)
ssp = &platform_info->ssp; ssp = &platform_info->ssp;
return pxa2xx_spi_probe(dev, ssp); pm_runtime_set_autosuspend_delay(dev, 50);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
ret = pxa2xx_spi_probe(dev, ssp, platform_info);
if (ret)
pm_runtime_disable(dev);
return ret;
} }
static void pxa2xx_spi_platform_remove(struct platform_device *pdev) static void pxa2xx_spi_platform_remove(struct platform_device *pdev)
{ {
pxa2xx_spi_remove(&pdev->dev); struct device *dev = &pdev->dev;
pm_runtime_get_sync(dev);
pxa2xx_spi_remove(dev);
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
} }
static const struct acpi_device_id pxa2xx_spi_acpi_match[] = { static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
......
...@@ -1277,16 +1277,15 @@ static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi) ...@@ -1277,16 +1277,15 @@ static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi)
return MAX_DMA_LEN; return MAX_DMA_LEN;
} }
int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp) int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp,
struct pxa2xx_spi_controller *platform_info)
{ {
struct pxa2xx_spi_controller *platform_info;
struct spi_controller *controller; struct spi_controller *controller;
struct driver_data *drv_data; struct driver_data *drv_data;
const struct lpss_config *config; const struct lpss_config *config;
int status; int status;
u32 tmp; u32 tmp;
platform_info = dev_get_platdata(dev);
if (platform_info->is_target) if (platform_info->is_target)
controller = devm_spi_alloc_target(dev, sizeof(*drv_data)); controller = devm_spi_alloc_target(dev, sizeof(*drv_data));
else else
...@@ -1450,24 +1449,16 @@ int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp) ...@@ -1450,24 +1449,16 @@ int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp)
} }
} }
pm_runtime_set_autosuspend_delay(dev, 50);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
/* Register with the SPI framework */ /* Register with the SPI framework */
dev_set_drvdata(dev, drv_data); dev_set_drvdata(dev, drv_data);
status = spi_register_controller(controller); status = spi_register_controller(controller);
if (status) { if (status) {
dev_err_probe(dev, status, "problem registering SPI controller\n"); dev_err_probe(dev, status, "problem registering SPI controller\n");
goto out_error_pm_runtime_enabled; goto out_error_clock_enabled;
} }
return status; return status;
out_error_pm_runtime_enabled:
pm_runtime_disable(dev);
out_error_clock_enabled: out_error_clock_enabled:
clk_disable_unprepare(ssp->clk); clk_disable_unprepare(ssp->clk);
...@@ -1484,8 +1475,6 @@ void pxa2xx_spi_remove(struct device *dev) ...@@ -1484,8 +1475,6 @@ void pxa2xx_spi_remove(struct device *dev)
struct driver_data *drv_data = dev_get_drvdata(dev); struct driver_data *drv_data = dev_get_drvdata(dev);
struct ssp_device *ssp = drv_data->ssp; struct ssp_device *ssp = drv_data->ssp;
pm_runtime_get_sync(dev);
spi_unregister_controller(drv_data->controller); spi_unregister_controller(drv_data->controller);
/* Disable the SSP at the peripheral and SOC level */ /* Disable the SSP at the peripheral and SOC level */
...@@ -1496,9 +1485,6 @@ void pxa2xx_spi_remove(struct device *dev) ...@@ -1496,9 +1485,6 @@ void pxa2xx_spi_remove(struct device *dev)
if (drv_data->controller_info->enable_dma) if (drv_data->controller_info->enable_dma)
pxa2xx_spi_dma_release(drv_data); pxa2xx_spi_dma_release(drv_data);
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
/* Release IRQ */ /* Release IRQ */
free_irq(ssp->irq, drv_data); free_irq(ssp->irq, drv_data);
} }
......
...@@ -132,7 +132,8 @@ extern void pxa2xx_spi_dma_stop(struct driver_data *drv_data); ...@@ -132,7 +132,8 @@ extern void pxa2xx_spi_dma_stop(struct driver_data *drv_data);
extern int pxa2xx_spi_dma_setup(struct driver_data *drv_data); extern int pxa2xx_spi_dma_setup(struct driver_data *drv_data);
extern void pxa2xx_spi_dma_release(struct driver_data *drv_data); extern void pxa2xx_spi_dma_release(struct driver_data *drv_data);
int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp); int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp,
struct pxa2xx_spi_controller *platform_info);
void pxa2xx_spi_remove(struct device *dev); void pxa2xx_spi_remove(struct device *dev);
extern const struct dev_pm_ops pxa2xx_spi_pm_ops; extern const struct dev_pm_ops pxa2xx_spi_pm_ops;
......
...@@ -1033,6 +1033,18 @@ static int __maybe_unused zynqmp_runtime_resume(struct device *dev) ...@@ -1033,6 +1033,18 @@ static int __maybe_unused zynqmp_runtime_resume(struct device *dev)
return 0; return 0;
} }
static unsigned long zynqmp_qspi_timeout(struct zynqmp_qspi *xqspi, u8 bits,
unsigned long bytes)
{
unsigned long timeout;
/* Assume we are at most 2x slower than the nominal bus speed */
timeout = mult_frac(bytes, 2 * 8 * MSEC_PER_SEC,
bits * xqspi->speed_hz);
/* And add 100 ms for scheduling delays */
return msecs_to_jiffies(timeout + 100);
}
/** /**
* zynqmp_qspi_exec_op() - Initiates the QSPI transfer * zynqmp_qspi_exec_op() - Initiates the QSPI transfer
* @mem: The SPI memory * @mem: The SPI memory
...@@ -1049,6 +1061,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, ...@@ -1049,6 +1061,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
{ {
struct zynqmp_qspi *xqspi = spi_controller_get_devdata struct zynqmp_qspi *xqspi = spi_controller_get_devdata
(mem->spi->controller); (mem->spi->controller);
unsigned long timeout;
int err = 0, i; int err = 0, i;
u32 genfifoentry = 0; u32 genfifoentry = 0;
u16 opcode = op->cmd.opcode; u16 opcode = op->cmd.opcode;
...@@ -1077,8 +1090,10 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, ...@@ -1077,8 +1090,10 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST, zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
GQSPI_IER_GENFIFOEMPTY_MASK | GQSPI_IER_GENFIFOEMPTY_MASK |
GQSPI_IER_TXNOT_FULL_MASK); GQSPI_IER_TXNOT_FULL_MASK);
if (!wait_for_completion_timeout timeout = zynqmp_qspi_timeout(xqspi, op->cmd.buswidth,
(&xqspi->data_completion, msecs_to_jiffies(1000))) { op->cmd.nbytes);
if (!wait_for_completion_timeout(&xqspi->data_completion,
timeout)) {
err = -ETIMEDOUT; err = -ETIMEDOUT;
goto return_err; goto return_err;
} }
...@@ -1104,8 +1119,10 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, ...@@ -1104,8 +1119,10 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
GQSPI_IER_TXEMPTY_MASK | GQSPI_IER_TXEMPTY_MASK |
GQSPI_IER_GENFIFOEMPTY_MASK | GQSPI_IER_GENFIFOEMPTY_MASK |
GQSPI_IER_TXNOT_FULL_MASK); GQSPI_IER_TXNOT_FULL_MASK);
if (!wait_for_completion_timeout timeout = zynqmp_qspi_timeout(xqspi, op->addr.buswidth,
(&xqspi->data_completion, msecs_to_jiffies(1000))) { op->addr.nbytes);
if (!wait_for_completion_timeout(&xqspi->data_completion,
timeout)) {
err = -ETIMEDOUT; err = -ETIMEDOUT;
goto return_err; goto return_err;
} }
...@@ -1173,8 +1190,9 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem, ...@@ -1173,8 +1190,9 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
GQSPI_IER_RXEMPTY_MASK); GQSPI_IER_RXEMPTY_MASK);
} }
} }
if (!wait_for_completion_timeout timeout = zynqmp_qspi_timeout(xqspi, op->data.buswidth,
(&xqspi->data_completion, msecs_to_jiffies(1000))) op->data.nbytes);
if (!wait_for_completion_timeout(&xqspi->data_completion, timeout))
err = -ETIMEDOUT; err = -ETIMEDOUT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment