Skip to content

Commit ebd1c4e

Browse files
committed
FROMLIST: spi: spi-qcom-qspi: Add interconnect support for memory path
The QSPI controller has two interconnect paths: 1. qspi-config: CPU to QSPI controller for register access 2. qspi-memory: QSPI controller to memory for DMA operations Currently, the driver only manages the qspi-config path. Add support for the qspi-memory path to ensure proper bandwidth allocation for QSPI data transfers to/from memory. Enable and disable both paths during runtime PM transitions. Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com> Link: https://lore.kernel.org/all/20260324-spi-nor-v1-2-3efe59c1c119@oss.qualcomm.com/
1 parent 6665026 commit ebd1c4e

1 file changed

Lines changed: 33 additions & 3 deletions

File tree

drivers/spi/spi-qcom-qspi.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ struct qcom_qspi {
174174
void *virt_cmd_desc[QSPI_MAX_SG];
175175
unsigned int n_cmd_desc;
176176
struct icc_path *icc_path_cpu_to_qspi;
177+
struct icc_path *icc_path_mem;
177178
unsigned long last_speed;
178179
/* Lock to protect data accessed by IRQs */
179180
spinlock_t lock;
@@ -272,7 +273,7 @@ static void qcom_qspi_handle_err(struct spi_controller *host,
272273
static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
273274
{
274275
int ret;
275-
unsigned int avg_bw_cpu;
276+
unsigned int avg_bw_cpu, avg_bw_mem;
276277

277278
if (speed_hz == ctrl->last_speed)
278279
return 0;
@@ -285,7 +286,7 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
285286
}
286287

287288
/*
288-
* Set BW quota for CPU.
289+
* Set BW quota for CPU and memory paths.
289290
* We don't have explicit peak requirement so keep it equal to avg_bw.
290291
*/
291292
avg_bw_cpu = Bps_to_icc(speed_hz);
@@ -296,6 +297,13 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
296297
return ret;
297298
}
298299

300+
avg_bw_mem = Bps_to_icc(speed_hz);
301+
ret = icc_set_bw(ctrl->icc_path_mem, avg_bw_mem, avg_bw_mem);
302+
if (ret) {
303+
dev_err(ctrl->dev, "ICC BW voting failed for memory: %d\n", ret);
304+
return ret;
305+
}
306+
299307
ctrl->last_speed = speed_hz;
300308

301309
return 0;
@@ -729,6 +737,11 @@ static int qcom_qspi_probe(struct platform_device *pdev)
729737
return dev_err_probe(dev, PTR_ERR(ctrl->icc_path_cpu_to_qspi),
730738
"Failed to get cpu path\n");
731739

740+
ctrl->icc_path_mem = devm_of_icc_get(dev, "qspi-memory");
741+
if (IS_ERR(ctrl->icc_path_mem))
742+
return dev_err_probe(dev, PTR_ERR(ctrl->icc_path_mem),
743+
"Failed to get memory path\n");
744+
732745
/* Set BW vote for register access */
733746
ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, Bps_to_icc(1000),
734747
Bps_to_icc(1000));
@@ -830,6 +843,13 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev)
830843
return ret;
831844
}
832845

846+
ret = icc_disable(ctrl->icc_path_mem);
847+
if (ret) {
848+
dev_err_ratelimited(ctrl->dev, "ICC disable failed for memory: %d\n", ret);
849+
icc_enable(ctrl->icc_path_cpu_to_qspi);
850+
return ret;
851+
}
852+
833853
pinctrl_pm_select_sleep_state(dev);
834854

835855
return 0;
@@ -850,9 +870,19 @@ static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev)
850870
return ret;
851871
}
852872

873+
ret = icc_enable(ctrl->icc_path_mem);
874+
if (ret) {
875+
dev_err_ratelimited(ctrl->dev, "ICC enable failed for memory: %d\n", ret);
876+
icc_disable(ctrl->icc_path_cpu_to_qspi);
877+
return ret;
878+
}
879+
853880
ret = clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks);
854-
if (ret)
881+
if (ret) {
882+
icc_disable(ctrl->icc_path_cpu_to_qspi);
883+
icc_disable(ctrl->icc_path_mem);
855884
return ret;
885+
}
856886

857887
return dev_pm_opp_set_rate(dev, ctrl->last_speed * 4);
858888
}

0 commit comments

Comments
 (0)