[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20260112190134.1526646-5-praveen.talari@oss.qualcomm.com>
Date: Tue, 13 Jan 2026 00:31:34 +0530
From: Praveen Talari <praveen.talari@....qualcomm.com>
To: Mark Brown <broonie@...nel.org>, Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Praveen Talari <praveen.talari@....qualcomm.com>,
linux-arm-msm@...r.kernel.org, linux-spi@...r.kernel.org,
devicetree@...r.kernel.org, linux-kernel@...r.kernel.org,
bryan.odonoghue@...aro.org, dmitry.baryshkov@....qualcomm.com,
andersson@...nel.org, bjorn.andersson@....qualcomm.com
Cc: prasad.sodagudi@....qualcomm.com, mukesh.savaliya@....qualcomm.com,
quic_vtanuku@...cinc.com, aniket.randive@....qualcomm.com,
chandana.chiluveru@....qualcomm.com
Subject: [PATCH v1 4/4] spi: qcom-geni: Enable SPI on SA8255p Qualcomm platforms
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().
Signed-off-by: Praveen Talari <praveen.talari@....qualcomm.com>
---
drivers/spi/spi-geni-qcom.c | 42 ++++++++++++++++++++++++++++++-------
1 file changed, 34 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index bf2b3d88693c..b1b41218f452 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -75,6 +75,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;
@@ -102,6 +109,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)
@@ -307,11 +315,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)
@@ -816,7 +825,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;
@@ -1040,7 +1049,9 @@ static int spi_geni_probe(struct platform_device *pdev)
mas->se.wrapper = dev_get_drvdata(dev->parent);
mas->se.base = base;
- ret = geni_se_resources_init(&mas->se);
+ mas->dev_data = device_get_match_data(&pdev->dev);
+
+ ret = mas->dev_data->resources_init(&mas->se);
if (ret)
return ret;
@@ -1097,7 +1108,8 @@ 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);
- return geni_se_resources_deactivate(&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)
@@ -1105,7 +1117,8 @@ static int __maybe_unused spi_geni_runtime_resume(struct device *dev)
struct spi_controller *spi = dev_get_drvdata(dev);
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
- return geni_se_resources_activate(&mas->se);
+ return mas->dev_data->power_on ?
+ mas->dev_data->power_on(&mas->se) : 0;
}
static int __maybe_unused spi_geni_suspend(struct device *dev)
@@ -1146,8 +1159,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);
--
2.34.1
Powered by blists - more mailing lists