Commit c2a905a6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -2000,13 +2000,25 @@ static int cqspi_runtime_resume(struct device *dev)
static int cqspi_suspend(struct device *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)
{
	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);
}
+29 −2
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@
#define TCR_RXMSK	BIT(19)
#define TCR_TXMSK	BIT(18)

struct fsl_lpspi_devtype_data {
	u8 prescale_max;
};

struct lpspi_config {
	u8 bpw;
	u8 chip_select;
@@ -119,10 +123,25 @@ struct fsl_lpspi_data {
	bool usedma;
	struct completion dma_rx_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[] = {
	{ .compatible = "fsl,imx7ulp-spi", },
	{ .compatible = "fsl,imx7ulp-spi", .data = &imx7ulp_lpspi_devtype_data,},
	{ .compatible = "fsl,imx93-spi", .data = &imx93_lpspi_devtype_data,},
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids);
@@ -297,9 +316,11 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
{
	struct lpspi_config config = fsl_lpspi->config;
	unsigned int perclk_rate, scldiv, div;
	u8 prescale_max;
	u8 prescale;

	perclk_rate = clk_get_rate(fsl_lpspi->clk_per);
	prescale_max = fsl_lpspi->devtype_data->prescale_max;

	if (!config.speed_hz) {
		dev_err(fsl_lpspi->dev,
@@ -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);

	for (prescale = 0; prescale < 8; prescale++) {
	for (prescale = 0; prescale < prescale_max; prescale++) {
		scldiv = div / (1 << prescale) - 2;
		if (scldiv < 256) {
			fsl_lpspi->config.prescale = prescale;
@@ -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)
{
	const struct fsl_lpspi_devtype_data *devtype_data;
	struct fsl_lpspi_data *fsl_lpspi;
	struct spi_controller *controller;
	struct resource *res;
@@ -830,6 +852,10 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
	u32 temp;
	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");
	if (is_target)
		controller = devm_spi_alloc_target(&pdev->dev,
@@ -848,6 +874,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
	fsl_lpspi->is_target = is_target;
	fsl_lpspi->is_only_cs1 = of_property_read_bool((&pdev->dev)->of_node,
						"fsl,spi-only-use-cs1-sel");
	fsl_lpspi->devtype_data = devtype_data;

	init_completion(&fsl_lpspi->xfer_done);

+14 −1
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/sprintf.h>
#include <linux/string.h>
#include <linux/types.h>
@@ -297,11 +298,23 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
		return ret;
	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)
{
	pm_runtime_forbid(&dev->dev);
	pm_runtime_get_noresume(&dev->dev);

	pxa2xx_spi_remove(&dev->dev);
}

+21 −5
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/types.h>

@@ -63,7 +64,7 @@ static struct ssp_device *pxa2xx_spi_ssp_request(struct platform_device *pdev)

	ssp = pxa_ssp_request(pdev->id, pdev->name);
	if (!ssp)
		return ssp;
		return NULL;

	status = devm_add_action_or_reset(&pdev->dev, pxa2xx_spi_ssp_release, ssp);
	if (status)
@@ -142,14 +143,13 @@ static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
	struct pxa2xx_spi_controller *platform_info;
	struct device *dev = &pdev->dev;
	struct ssp_device *ssp;
	int ret;

	platform_info = dev_get_platdata(dev);
	if (!platform_info) {
		platform_info = pxa2xx_spi_init_pdata(pdev);
		if (IS_ERR(platform_info))
			return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");

		dev->platform_data = platform_info;
	}

	ssp = pxa2xx_spi_ssp_request(pdev);
@@ -158,12 +158,28 @@ static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
	if (!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)
{
	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[] = {
+3 −17
Original line number Diff line number Diff line
@@ -1277,16 +1277,15 @@ static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi)
	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 driver_data *drv_data;
	const struct lpss_config *config;
	int status;
	u32 tmp;

	platform_info = dev_get_platdata(dev);
	if (platform_info->is_target)
		controller = devm_spi_alloc_target(dev, sizeof(*drv_data));
	else
@@ -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 */
	dev_set_drvdata(dev, drv_data);
	status = spi_register_controller(controller);
	if (status) {
		dev_err_probe(dev, status, "problem registering SPI controller\n");
		goto out_error_pm_runtime_enabled;
		goto out_error_clock_enabled;
	}

	return status;

out_error_pm_runtime_enabled:
	pm_runtime_disable(dev);

out_error_clock_enabled:
	clk_disable_unprepare(ssp->clk);

@@ -1484,8 +1475,6 @@ void pxa2xx_spi_remove(struct device *dev)
	struct driver_data *drv_data = dev_get_drvdata(dev);
	struct ssp_device *ssp = drv_data->ssp;

	pm_runtime_get_sync(dev);

	spi_unregister_controller(drv_data->controller);

	/* Disable the SSP at the peripheral and SOC level */
@@ -1496,9 +1485,6 @@ void pxa2xx_spi_remove(struct device *dev)
	if (drv_data->controller_info->enable_dma)
		pxa2xx_spi_dma_release(drv_data);

	pm_runtime_put_noidle(dev);
	pm_runtime_disable(dev);

	/* Release IRQ */
	free_irq(ssp->irq, drv_data);
}
Loading