summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-07-06 14:30:06 +0100
committerMark Brown <broonie@kernel.org>2026-07-06 14:30:06 +0100
commit4f98f533f6470507d62a3ee4a4ba74de40772667 (patch)
tree9793f9641665248a971254e6531231579be7768f /drivers/spi
parent5d14285d60ba95561609a293064654a0c7d7d928 (diff)
parentb3e1d0948ca94a16a81ea8cc26c6246e6cc44943 (diff)
downloadlinux-next-4f98f533f6470507d62a3ee4a4ba74de40772667.tar.gz
linux-next-4f98f533f6470507d62a3ee4a4ba74de40772667.zip
spi: Enable SPI on SA8255p Qualcomm platforms
Praveen Talari <praveen.talari@oss.qualcomm.com> says: The Qualcomm automotive SA8255p SoC relies on firmware to configure platform resources, including clocks, interconnects and TLMM. The driver requests resources operations over SCMI using power and performance protocols. The SCMI power protocol enables or disables resources like clocks, interconnect paths, and TLMM (GPIOs) using runtime PM framework APIs, such as resume/suspend, to control power states(on/off). The SCMI performance protocol manages SPI frequency, with each frequency rate represented by a performance level. The driver uses geni_se_set_perf_opp() API to request the desired frequency rate. As part of geni_se_set_perf_opp(), the OPP for the requested frequency is obtained using dev_pm_opp_find_freq_floor() and the performance level is set using dev_pm_opp_set_opp(). Link: https://patch.msgid.link/20260618-enable-spi-on-sa8255p-v4-0-f5b5067e7e1e@oss.qualcomm.com
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-atcspi200.c1
-rw-r--r--drivers/spi/spi-cs42l43.c1
-rw-r--r--drivers/spi/spi-dw-core.c2
-rw-r--r--drivers/spi/spi-dw-dma.c3
-rw-r--r--drivers/spi/spi-geni-qcom.c88
-rw-r--r--drivers/spi/spi-gpio.c1
-rw-r--r--drivers/spi/spi-hisi-sfc-v3xx.c1
-rw-r--r--drivers/spi/spi-loongson-pci.c1
-rw-r--r--drivers/spi/spi-loongson-plat.c1
-rw-r--r--drivers/spi/spi-loopback-test.c1
-rw-r--r--drivers/spi/spi-offload-trigger-adi-util-sigma-delta.c1
-rw-r--r--drivers/spi/spi-offload-trigger-pwm.c1
-rw-r--r--drivers/spi/spi-pxa2xx-platform.c1
-rw-r--r--drivers/spi/spi-realtek-rtl-snand.c1
-rw-r--r--drivers/spi/spi-realtek-rtl.c1
-rw-r--r--drivers/spi/spi-rzv2h-rspi.c4
-rw-r--r--drivers/spi/spi-sc18is602.c1
-rw-r--r--drivers/spi/spi-wpcm-fiu.c1
-rw-r--r--drivers/spi/spi.c1
-rw-r--r--drivers/spi/spidev.c1
20 files changed, 47 insertions, 66 deletions
diff --git a/drivers/spi/spi-atcspi200.c b/drivers/spi/spi-atcspi200.c
index e0fd101a62bc..b6ea8e556335 100644
--- a/drivers/spi/spi-atcspi200.c
+++ b/drivers/spi/spi-atcspi200.c
@@ -15,7 +15,6 @@
#include <linux/jiffies.h>
#include <linux/minmax.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c
index 6961e36b89d1..7106a8a4f280 100644
--- a/drivers/spi/spi-cs42l43.c
+++ b/drivers/spi/spi-cs42l43.c
@@ -17,7 +17,6 @@
#include <linux/gpio/property.h>
#include <linux/mfd/cs42l43.h>
#include <linux/mfd/cs42l43-regs.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index eff08461c2f5..ad8aad958c76 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -949,7 +949,7 @@ int dw_spi_add_controller(struct device *dev, struct dw_spi *dws)
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
ctlr);
if (ret < 0 && ret != -ENOTCONN) {
- dev_err(dev, "can not get IRQ\n");
+ dev_err(dev, "can not request IRQ\n");
goto err_free_ctlr;
}
diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c
index fe726b9b1780..bd70a7ed8067 100644
--- a/drivers/spi/spi-dw-dma.c
+++ b/drivers/spi/spi-dw-dma.c
@@ -247,11 +247,12 @@ static bool dw_spi_can_dma(struct spi_controller *ctlr,
{
struct dw_spi *dws = spi_controller_get_devdata(ctlr);
enum dma_slave_buswidth dma_bus_width;
+ u8 n_bytes = roundup_pow_of_two(BITS_TO_BYTES(xfer->bits_per_word));
if (xfer->len <= dws->fifo_len)
return false;
- dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes);
+ dma_bus_width = dw_spi_dma_convert_width(n_bytes);
return dws->dma_addr_widths & BIT(dma_bus_width);
}
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 26e723cfea61..88ac0833351c 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -78,6 +78,13 @@
#define GSI_CPHA BIT(4)
#define GSI_CPOL BIT(5)
+struct geni_spi_desc {
+ int (*resources_init)(struct geni_se *se);
+ int (*set_rate)(struct geni_se *se, unsigned long clk_freq);
+ int (*power_on)(struct geni_se *se);
+ int (*power_off)(struct geni_se *se);
+};
+
struct spi_geni_master {
struct geni_se se;
struct device *dev;
@@ -105,6 +112,7 @@ struct spi_geni_master {
struct dma_chan *tx;
struct dma_chan *rx;
int cur_xfer_mode;
+ const struct geni_spi_desc *dev_data;
};
static void spi_slv_setup(struct spi_geni_master *mas)
@@ -305,11 +313,12 @@ static void spi_setup_word_len(struct spi_geni_master *mas, u16 mode,
writel(word_len, se->base + SE_SPI_WORD_LEN);
}
-static int geni_spi_set_clock_and_bw(struct spi_geni_master *mas,
- unsigned long clk_hz)
+static int geni_spi_set_clock_and_bw(struct geni_se *se,
+ unsigned long clk_hz)
{
+ struct spi_controller *spi = dev_get_drvdata(se->dev);
+ struct spi_geni_master *mas = spi_controller_get_devdata(spi);
u32 clk_sel, m_clk_cfg, idx, div;
- struct geni_se *se = &mas->se;
int ret;
if (clk_hz == mas->cur_speed_hz)
@@ -825,7 +834,7 @@ static int setup_se_xfer(struct spi_transfer *xfer,
}
/* Speed and bits per word can be overridden per transfer */
- ret = geni_spi_set_clock_and_bw(mas, xfer->speed_hz);
+ ret = mas->dev_data->set_rate(&mas->se, xfer->speed_hz);
if (ret)
return ret;
@@ -1045,7 +1054,6 @@ static int spi_geni_probe(struct platform_device *pdev)
struct spi_controller *spi;
struct spi_geni_master *mas;
void __iomem *base;
- struct clk *clk;
struct device *dev = &pdev->dev;
irq = platform_get_irq(pdev, 0);
@@ -1060,10 +1068,6 @@ static int spi_geni_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- clk = devm_clk_get(dev, "se");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
if (device_property_read_bool(dev, "spi-slave"))
spi = devm_spi_alloc_target(dev, sizeof(*mas));
else
@@ -1079,17 +1083,14 @@ static int spi_geni_probe(struct platform_device *pdev)
mas->se.dev = dev;
mas->se.wrapper = dev_get_drvdata(dev->parent);
mas->se.base = base;
- mas->se.clk = clk;
- ret = devm_pm_opp_set_clkname(&pdev->dev, "se");
+ mas->dev_data = device_get_match_data(&pdev->dev);
+ if (!mas->dev_data)
+ return -EINVAL;
+
+ ret = mas->dev_data->resources_init(&mas->se);
if (ret)
return ret;
- /* OPP table is optional */
- ret = devm_pm_opp_of_add_table(&pdev->dev);
- if (ret && ret != -ENODEV) {
- dev_err(&pdev->dev, "invalid OPP table in device tree\n");
- return ret;
- }
spi->bus_num = -1;
spi->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_CS_HIGH;
@@ -1115,24 +1116,12 @@ static int spi_geni_probe(struct platform_device *pdev)
if (spi->target)
spi->target_abort = spi_geni_target_abort;
- ret = geni_icc_get(&mas->se, NULL);
- if (ret)
- return ret;
-
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 250);
ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;
- /* Set the bus quota to a reasonable value for register access */
- mas->se.icc_paths[GENI_TO_CORE].avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
- mas->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
-
- ret = geni_icc_set_bw(&mas->se);
- if (ret)
- return ret;
-
ret = spi_geni_init(mas);
if (ret)
return ret;
@@ -1154,16 +1143,9 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev)
{
struct spi_controller *spi = dev_get_drvdata(dev);
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
- int ret;
- /* Drop the performance state vote */
- dev_pm_opp_set_rate(dev, 0);
-
- ret = geni_se_resources_off(&mas->se);
- if (ret)
- return ret;
-
- return geni_icc_disable(&mas->se);
+ return mas->dev_data->power_off ?
+ mas->dev_data->power_off(&mas->se) : 0;
}
static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
@@ -1172,15 +1154,16 @@ static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
int ret;
- ret = geni_icc_enable(&mas->se);
- if (ret)
- return ret;
+ if (mas->dev_data->power_on) {
+ ret = mas->dev_data->power_on(&mas->se);
+ if (ret)
+ return ret;
+ }
- ret = geni_se_resources_on(&mas->se);
- if (ret)
- return ret;
+ if (mas->se.has_opp)
+ return dev_pm_opp_set_rate(mas->dev, mas->cur_sclk_hz);
- return dev_pm_opp_set_rate(mas->dev, mas->cur_sclk_hz);
+ return 0;
}
static int __maybe_unused spi_geni_suspend(struct device *dev)
@@ -1221,8 +1204,21 @@ static const struct dev_pm_ops spi_geni_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(spi_geni_suspend, spi_geni_resume)
};
+static const struct geni_spi_desc geni_spi = {
+ .resources_init = geni_se_resources_init,
+ .set_rate = geni_spi_set_clock_and_bw,
+ .power_on = geni_se_resources_activate,
+ .power_off = geni_se_resources_deactivate,
+};
+
+static const struct geni_spi_desc sa8255p_geni_spi = {
+ .resources_init = geni_se_domain_attach,
+ .set_rate = geni_se_set_perf_opp,
+};
+
static const struct of_device_id spi_geni_dt_match[] = {
- { .compatible = "qcom,geni-spi" },
+ { .compatible = "qcom,geni-spi", .data = &geni_spi },
+ { .compatible = "qcom,sa8255p-geni-spi", .data = &sa8255p_geni_spi },
{}
};
MODULE_DEVICE_TABLE(of, spi_geni_dt_match);
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 072127a38fad..c32c33b27e1a 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -7,7 +7,6 @@
*/
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c
index eeeb86381862..d60db579b0fb 100644
--- a/drivers/spi/spi-hisi-sfc-v3xx.c
+++ b/drivers/spi/spi-hisi-sfc-v3xx.c
@@ -11,7 +11,6 @@
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
diff --git a/drivers/spi/spi-loongson-pci.c b/drivers/spi/spi-loongson-pci.c
index cbcde153260e..2fe5419a8dd2 100644
--- a/drivers/spi/spi-loongson-pci.c
+++ b/drivers/spi/spi-loongson-pci.c
@@ -2,7 +2,6 @@
// PCI interface driver for Loongson SPI Support
// Copyright (C) 2023 Loongson Technology Corporation Limited
-#include <linux/mod_devicetable.h>
#include <linux/pci.h>
#include "spi-loongson.h"
diff --git a/drivers/spi/spi-loongson-plat.c b/drivers/spi/spi-loongson-plat.c
index 64a7270f9a64..550b237838c0 100644
--- a/drivers/spi/spi-loongson-plat.c
+++ b/drivers/spi/spi-loongson-plat.c
@@ -3,7 +3,6 @@
// Copyright (C) 2023 Loongson Technology Corporation Limited
#include <linux/err.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include "spi-loongson.h"
diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c
index e0b131aa29b6..066386abadac 100644
--- a/drivers/spi/spi-loopback-test.c
+++ b/drivers/spi/spi-loopback-test.c
@@ -14,7 +14,6 @@
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/list_sort.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/vmalloc.h>
diff --git a/drivers/spi/spi-offload-trigger-adi-util-sigma-delta.c b/drivers/spi/spi-offload-trigger-adi-util-sigma-delta.c
index 8468c773713a..c4c25c2cc4b5 100644
--- a/drivers/spi/spi-offload-trigger-adi-util-sigma-delta.c
+++ b/drivers/spi/spi-offload-trigger-adi-util-sigma-delta.c
@@ -7,7 +7,6 @@
#include <linux/clk.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
diff --git a/drivers/spi/spi-offload-trigger-pwm.c b/drivers/spi/spi-offload-trigger-pwm.c
index 3e8c19227edb..0eff14328a6b 100644
--- a/drivers/spi/spi-offload-trigger-pwm.c
+++ b/drivers/spi/spi-offload-trigger-pwm.c
@@ -9,7 +9,6 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/math.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
diff --git a/drivers/spi/spi-pxa2xx-platform.c b/drivers/spi/spi-pxa2xx-platform.c
index 45e159e75a52..849a14cd0343 100644
--- a/drivers/spi/spi-pxa2xx-platform.c
+++ b/drivers/spi/spi-pxa2xx-platform.c
@@ -5,7 +5,6 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
diff --git a/drivers/spi/spi-realtek-rtl-snand.c b/drivers/spi/spi-realtek-rtl-snand.c
index 7d5853d202c6..61fe54d8167a 100644
--- a/drivers/spi/spi-realtek-rtl-snand.c
+++ b/drivers/spi/spi-realtek-rtl-snand.c
@@ -3,7 +3,6 @@
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
diff --git a/drivers/spi/spi-realtek-rtl.c b/drivers/spi/spi-realtek-rtl.c
index d7acc02105ca..73065c8934dc 100644
--- a/drivers/spi/spi-realtek-rtl.c
+++ b/drivers/spi/spi-realtek-rtl.c
@@ -2,7 +2,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
struct rtspi {
diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c
index 0738d448160d..daa4239b0fe0 100644
--- a/drivers/spi/spi-rzv2h-rspi.c
+++ b/drivers/spi/spi-rzv2h-rspi.c
@@ -366,14 +366,14 @@ static int rzv2h_rspi_transfer_dma(struct rzv2h_rspi_priv *rspi,
rzv2h_rspi_clear_all_irqs(rspi);
ret = wait_event_interruptible_timeout(rspi->wait, rspi->dma_callbacked, HZ);
- if (ret) {
+ if (ret > 0) {
dmaengine_synchronize(rspi->controller->dma_tx);
dmaengine_synchronize(rspi->controller->dma_rx);
ret = 0;
} else {
dmaengine_terminate_sync(rspi->controller->dma_tx);
dmaengine_terminate_sync(rspi->controller->dma_rx);
- ret = -ETIMEDOUT;
+ ret = ret ?: -ETIMEDOUT;
}
enable_irq(rspi->irq_rx);
diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c
index ae534ebd5e87..ebd5c172efda 100644
--- a/drivers/spi/spi-sc18is602.c
+++ b/drivers/spi/spi-sc18is602.c
@@ -7,7 +7,6 @@
#include <linux/kernel.h>
#include <linux/err.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/i2c.h>
diff --git a/drivers/spi/spi-wpcm-fiu.c b/drivers/spi/spi-wpcm-fiu.c
index cd78e927953d..884e5042bad5 100644
--- a/drivers/spi/spi-wpcm-fiu.c
+++ b/drivers/spi/spi-wpcm-fiu.c
@@ -3,7 +3,6 @@
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 46152f6acb76..d9e6b4b87c89 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -19,7 +19,6 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
-#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 638221178384..15d2aaeb08e9 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -14,7 +14,6 @@
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/property.h>