Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ properties:
compatible:
items:
- enum:
- qcom,qcs615-qspi
- qcom,sc7180-qspi
- qcom,sc7280-qspi
- qcom,sdm845-qspi
Expand Down
12 changes: 12 additions & 0 deletions arch/arm64/boot/dts/qcom/qcs615-ride.dts
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,18 @@
};
};

&qspi {
status = "okay";

flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <25000000>;
spi-tx-bus-width = <2>;
spi-rx-bus-width = <2>;
};
};

&qupv3_id_0 {
status = "okay";
};
Expand Down
80 changes: 80 additions & 0 deletions arch/arm64/boot/dts/qcom/talos.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,25 @@

};

qspi_opp_table: opp-table-qspi {
compatible = "operating-points-v2";

opp-60000000 {
opp-hz = /bits/ 64 <60000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};

opp-133250000 {
opp-hz = /bits/ 64 <133250000>;
required-opps = <&rpmhpd_opp_svs>;
};

opp-266500000 {
opp-hz = /bits/ 64 <266500000>;
required-opps = <&rpmhpd_opp_nom>;
};
};

qup_opp_table: opp-table-qup {
compatible = "operating-points-v2";

Expand Down Expand Up @@ -1622,6 +1641,34 @@
bias-pull-up;
};

qspi_cs0: qspi-cs0-state {
pins = "gpio44";
function = "qspi";
bias-disable;
drive-strength = <6>;
};

qspi_data0123: qspi-data0123-state {
pins = "gpio45", "gpio46", "gpio47", "gpio49";
function = "qspi";
bias-pull-down;
drive-strength = <6>;
};

qspi_clk: qspi-clk-state {
pins = "gpio48";
function = "qspi";
bias-pull-down;
drive-strength = <6>;
};

qspi_cs1: qspi-cs1-state {
pins = "gpio50";
function = "qspi";
bias-pull-down;
drive-strength = <6>;
};

qup_i2c1_data_clk: qup-i2c1-data-clk-state {
pins = "gpio4", "gpio5";
function = "qup0";
Expand Down Expand Up @@ -3916,6 +3963,39 @@
};
};

qspi: spi@88df000 {
compatible = "qcom,qcs615-qspi",
"qcom,qspi-v1";
reg = <0x0 0x088df000 0x0 0x1000>;

interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH 0>;

clocks = <&gcc GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
<&gcc GCC_QSPI_CORE_CLK>;
clock-names = "iface",
"core";

interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
&config_noc SLAVE_QSPI QCOM_ICC_TAG_ALWAYS>,
<&aggre1_noc MASTER_QSPI QCOM_ICC_TAG_ALWAYS
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
interconnect-names = "qspi-config",
"qspi-memory";

power-domains = <&rpmhpd RPMHPD_CX>;
operating-points-v2 = <&qspi_opp_table>;

iommus = <&apps_smmu 0x160 0x0>;

pinctrl-0 = <&qspi_clk>, <&qspi_cs0>, <&qspi_data0123>;
pinctrl-names = "default";

#address-cells = <1>;
#size-cells = <0>;

status = "disabled";
};

dc_noc: interconnect@9160000 {
reg = <0x0 0x09160000 0x0 0x3200>;
compatible = "qcom,qcs615-dc-noc";
Expand Down
36 changes: 33 additions & 3 deletions drivers/spi/spi-qcom-qspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ struct qcom_qspi {
void *virt_cmd_desc[QSPI_MAX_SG];
unsigned int n_cmd_desc;
struct icc_path *icc_path_cpu_to_qspi;
struct icc_path *icc_path_mem;
unsigned long last_speed;
/* Lock to protect data accessed by IRQs */
spinlock_t lock;
Expand Down Expand Up @@ -272,7 +273,7 @@ static void qcom_qspi_handle_err(struct spi_controller *host,
static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
{
int ret;
unsigned int avg_bw_cpu;
unsigned int avg_bw_cpu, avg_bw_mem;

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

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

avg_bw_mem = Bps_to_icc(speed_hz);
ret = icc_set_bw(ctrl->icc_path_mem, avg_bw_mem, avg_bw_mem);
if (ret) {
dev_err(ctrl->dev, "ICC BW voting failed for memory: %d\n", ret);
return ret;
}

ctrl->last_speed = speed_hz;

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

ctrl->icc_path_mem = devm_of_icc_get(dev, "qspi-memory");
if (IS_ERR(ctrl->icc_path_mem))
return dev_err_probe(dev, PTR_ERR(ctrl->icc_path_mem),
"Failed to get memory path\n");

/* Set BW vote for register access */
ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, Bps_to_icc(1000),
Bps_to_icc(1000));
Expand Down Expand Up @@ -830,6 +843,13 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev)
return ret;
}

ret = icc_disable(ctrl->icc_path_mem);
if (ret) {
dev_err_ratelimited(ctrl->dev, "ICC disable failed for memory: %d\n", ret);
icc_enable(ctrl->icc_path_cpu_to_qspi);
return ret;
}

pinctrl_pm_select_sleep_state(dev);

return 0;
Expand All @@ -850,9 +870,19 @@ static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev)
return ret;
}

ret = icc_enable(ctrl->icc_path_mem);
if (ret) {
dev_err_ratelimited(ctrl->dev, "ICC enable failed for memory: %d\n", ret);
icc_disable(ctrl->icc_path_cpu_to_qspi);
return ret;
}

ret = clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks);
if (ret)
if (ret) {
icc_disable(ctrl->icc_path_cpu_to_qspi);
icc_disable(ctrl->icc_path_mem);
return ret;
}

return dev_pm_opp_set_rate(dev, ctrl->last_speed * 4);
}
Expand Down