Skip to content

Commit 31f8843

Browse files
authored
Enable ICE clock scaling (#460)
Enable ICE clock scaling
2 parents a3e53ba + bea7054 commit 31f8843

7 files changed

Lines changed: 239 additions & 1 deletion

File tree

Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ properties:
4040
power-domains:
4141
maxItems: 1
4242

43+
operating-points-v2: true
44+
45+
opp-table:
46+
type: object
47+
4348
required:
4449
- compatible
4550
- reg
@@ -79,5 +84,26 @@ examples:
7984
clock-names = "core",
8085
"iface";
8186
power-domains = <&gcc UFS_PHY_GDSC>;
87+
88+
operating-points-v2 = <&ice_opp_table>;
89+
90+
ice_opp_table: opp-table {
91+
compatible = "operating-points-v2";
92+
93+
opp-100000000 {
94+
opp-hz = /bits/ 64 <100000000>;
95+
required-opps = <&rpmhpd_opp_low_svs>;
96+
};
97+
98+
opp-201500000 {
99+
opp-hz = /bits/ 64 <201500000>;
100+
required-opps = <&rpmhpd_opp_svs_l1>;
101+
};
102+
103+
opp-403000000 {
104+
opp-hz = /bits/ 64 <403000000>;
105+
required-opps = <&rpmhpd_opp_nom>;
106+
};
107+
};
82108
};
83109
...

arch/arm64/boot/dts/qcom/monaco.dtsi

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,22 @@
26672667
clock-names = "core",
26682668
"iface";
26692669
power-domains = <&gcc GCC_UFS_PHY_GDSC>;
2670+
2671+
operating-points-v2 = <&ice_opp_table>;
2672+
2673+
ice_opp_table: opp-table {
2674+
compatible = "operating-points-v2";
2675+
2676+
opp-201600000 {
2677+
opp-hz = /bits/ 64 <201600000>;
2678+
required-opps = <&rpmhpd_opp_svs_l1>;
2679+
};
2680+
2681+
opp-403200000 {
2682+
opp-hz = /bits/ 64 <403200000>;
2683+
required-opps = <&rpmhpd_opp_nom>;
2684+
};
2685+
};
26702686
};
26712687

26722688
crypto: crypto@1dfa000 {
@@ -4570,6 +4586,22 @@
45704586
clock-names = "core",
45714587
"iface";
45724588
power-domains = <&rpmhpd RPMHPD_CX>;
4589+
4590+
operating-points-v2 = <&ice_mmc_opp_table>;
4591+
4592+
ice_mmc_opp_table: opp-table {
4593+
compatible = "operating-points-v2";
4594+
4595+
opp-150000000 {
4596+
opp-hz = /bits/ 64 <150000000>;
4597+
required-opps = <&rpmhpd_opp_svs_l1>;
4598+
};
4599+
4600+
opp-300000000 {
4601+
opp-hz = /bits/ 64 <300000000>;
4602+
required-opps = <&rpmhpd_opp_nom>;
4603+
};
4604+
};
45734605
};
45744606

45754607
usb_1_hsphy: phy@8904000 {

arch/arm64/boot/dts/qcom/sc7280.dtsi

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,27 @@
10871087
clock-names = "core",
10881088
"iface";
10891089
power-domains = <&rpmhpd SC7280_CX>;
1090+
1091+
operating-points-v2 = <&ice_mmc_opp_table>;
1092+
1093+
ice_mmc_opp_table: opp-table {
1094+
compatible = "operating-points-v2";
1095+
1096+
opp-100000000 {
1097+
opp-hz = /bits/ 64 <100000000>;
1098+
required-opps = <&rpmhpd_opp_low_svs>;
1099+
};
1100+
1101+
opp-150000000 {
1102+
opp-hz = /bits/ 64 <150000000>;
1103+
required-opps = <&rpmhpd_opp_svs>;
1104+
};
1105+
1106+
opp-300000000 {
1107+
opp-hz = /bits/ 64 <300000000>;
1108+
required-opps = <&rpmhpd_opp_nom>;
1109+
};
1110+
};
10901111
};
10911112

10921113
gpi_dma0: dma-controller@900000 {
@@ -2597,6 +2618,27 @@
25972618
clock-names = "core",
25982619
"iface";
25992620
power-domains = <&gcc GCC_UFS_PHY_GDSC>;
2621+
2622+
operating-points-v2 = <&ice_opp_table>;
2623+
2624+
ice_opp_table: opp-table {
2625+
compatible = "operating-points-v2";
2626+
2627+
opp-75000000 {
2628+
opp-hz = /bits/ 64 <75000000>;
2629+
required-opps = <&rpmhpd_opp_low_svs>;
2630+
};
2631+
2632+
opp-150000000 {
2633+
opp-hz = /bits/ 64 <150000000>;
2634+
required-opps = <&rpmhpd_opp_svs>;
2635+
};
2636+
2637+
opp-300000000 {
2638+
opp-hz = /bits/ 64 <300000000>;
2639+
required-opps = <&rpmhpd_opp_nom>;
2640+
};
2641+
};
26002642
};
26012643

26022644
cryptobam: dma-controller@1dc4000 {

drivers/mmc/host/sdhci-msm.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,6 +1889,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
18891889
#ifdef CONFIG_MMC_CRYPTO
18901890

18911891
static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops; /* forward decl */
1892+
static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
1893+
bool round_ceil); /* forward decl */
18921894

18931895
static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
18941896
struct cqhci_host *cq_host)
@@ -1948,6 +1950,11 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
19481950

19491951
mmc->caps2 |= MMC_CAP2_CRYPTO;
19501952
mmc->caps2 |= MMC_CAP2_CRYPTO_NO_REPROG;
1953+
1954+
err = sdhci_msm_ice_scale_clk(msm_host, INT_MAX, false);
1955+
if (err && err != -EOPNOTSUPP)
1956+
dev_warn(dev, "Unable to boost ICE clock to TURBO\n");
1957+
19511958
return 0;
19521959
}
19531960

@@ -1973,6 +1980,16 @@ static int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
19731980
return 0;
19741981
}
19751982

1983+
static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host,
1984+
unsigned long target_freq,
1985+
bool round_ceil)
1986+
{
1987+
if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
1988+
return qcom_ice_scale_clk(msm_host->ice, target_freq, round_ceil);
1989+
1990+
return 0;
1991+
}
1992+
19761993
static inline struct sdhci_msm_host *
19771994
sdhci_msm_host_from_crypto_profile(struct blk_crypto_profile *profile)
19781995
{
@@ -2076,6 +2093,13 @@ sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
20762093
{
20772094
return 0;
20782095
}
2096+
2097+
static inline int
2098+
sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
2099+
bool round_ceil)
2100+
{
2101+
return 0;
2102+
}
20792103
#endif /* !CONFIG_MMC_CRYPTO */
20802104

20812105
/*****************************************************************************\

drivers/soc/qcom/ice.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/of.h>
1717
#include <linux/of_platform.h>
1818
#include <linux/platform_device.h>
19+
#include <linux/pm_opp.h>
1920

2021
#include <linux/firmware/qcom/qcom_scm.h>
2122

@@ -112,6 +113,8 @@ struct qcom_ice {
112113
bool use_hwkm;
113114
bool hwkm_init_complete;
114115
u8 hwkm_version;
116+
unsigned long core_clk_freq;
117+
bool has_opp;
115118
};
116119

117120
static bool qcom_ice_check_supported(struct qcom_ice *ice)
@@ -311,6 +314,10 @@ int qcom_ice_resume(struct qcom_ice *ice)
311314
struct device *dev = ice->dev;
312315
int err;
313316

317+
/* Restore the ICE core clk freq */
318+
if (ice->has_opp && ice->core_clk_freq)
319+
dev_pm_opp_set_rate(ice->dev, ice->core_clk_freq);
320+
314321
err = clk_prepare_enable(ice->core_clk);
315322
if (err) {
316323
dev_err(dev, "Failed to enable core clock: %d\n", err);
@@ -331,6 +338,11 @@ int qcom_ice_suspend(struct qcom_ice *ice)
331338
{
332339
clk_disable_unprepare(ice->iface_clk);
333340
clk_disable_unprepare(ice->core_clk);
341+
342+
/* Drop the clock votes while suspend */
343+
if (ice->has_opp)
344+
dev_pm_opp_set_rate(ice->dev, 0);
345+
334346
ice->hwkm_init_complete = false;
335347

336348
return 0;
@@ -556,6 +568,51 @@ int qcom_ice_import_key(struct qcom_ice *ice,
556568
}
557569
EXPORT_SYMBOL_GPL(qcom_ice_import_key);
558570

571+
/**
572+
* qcom_ice_scale_clk() - Scale ICE clock for DVFS-aware operations
573+
* @ice: ICE driver data
574+
* @target_freq: requested frequency in Hz
575+
* @round_ceil: when true, selects nearest freq >= @target_freq;
576+
* otherwise, selects nearest freq <= @target_freq
577+
*
578+
* Selects an OPP frequency based on @target_freq and the rounding direction
579+
* specified by @round_ceil, then programs it using dev_pm_opp_set_rate(),
580+
* including any voltage or power-domain transitions handled by the OPP
581+
* framework. Updates ice->core_clk_freq on success.
582+
*
583+
* Return: 0 on success; -EOPNOTSUPP if no OPP table; or error from
584+
* dev_pm_opp_set_rate()/OPP lookup.
585+
*/
586+
int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
587+
bool round_ceil)
588+
{
589+
unsigned long ice_freq = target_freq;
590+
struct dev_pm_opp *opp;
591+
int ret;
592+
593+
if (!ice->has_opp)
594+
return -EOPNOTSUPP;
595+
596+
if (round_ceil)
597+
opp = dev_pm_opp_find_freq_ceil(ice->dev, &ice_freq);
598+
else
599+
opp = dev_pm_opp_find_freq_floor(ice->dev, &ice_freq);
600+
601+
if (IS_ERR(opp))
602+
return PTR_ERR(opp);
603+
dev_pm_opp_put(opp);
604+
605+
ret = dev_pm_opp_set_rate(ice->dev, ice_freq);
606+
if (ret) {
607+
dev_err(ice->dev, "Unable to scale ICE clock rate\n");
608+
return ret;
609+
}
610+
ice->core_clk_freq = ice_freq;
611+
612+
return ret;
613+
}
614+
EXPORT_SYMBOL_GPL(qcom_ice_scale_clk);
615+
559616
static struct qcom_ice *qcom_ice_create(struct device *dev,
560617
void __iomem *base)
561618
{
@@ -731,6 +788,7 @@ static int qcom_ice_probe(struct platform_device *pdev)
731788
{
732789
struct qcom_ice *engine;
733790
void __iomem *base;
791+
int err;
734792

735793
base = devm_platform_ioremap_resource(pdev, 0);
736794
if (IS_ERR(base)) {
@@ -742,6 +800,40 @@ static int qcom_ice_probe(struct platform_device *pdev)
742800
if (IS_ERR(engine))
743801
return PTR_ERR(engine);
744802

803+
/* qcom_ice_create() may return NULL if scm calls are not available */
804+
if (!engine)
805+
return -EOPNOTSUPP;
806+
807+
err = devm_pm_opp_set_clkname(&pdev->dev, "core");
808+
if (err && err != -ENOENT) {
809+
dev_err(&pdev->dev, "Unable to set core clkname to OPP-table\n");
810+
return err;
811+
}
812+
813+
/* OPP table is optional */
814+
err = devm_pm_opp_of_add_table(&pdev->dev);
815+
if (err && err != -ENODEV) {
816+
dev_err(&pdev->dev, "Invalid OPP table in Device tree\n");
817+
return err;
818+
}
819+
820+
/*
821+
* The OPP table is optional. devm_pm_opp_of_add_table() returns
822+
* -ENODEV when no OPP table is present in DT, which is not treated
823+
* as an error. Therefore, track successful OPP registration only
824+
* when the return value is 0.
825+
*/
826+
engine->has_opp = (err == 0);
827+
if (!engine->has_opp)
828+
dev_info(&pdev->dev, "ICE OPP table is not registered, please update your DT\n");
829+
830+
/*
831+
* Store the core clock rate for suspend resume cycles,
832+
* against OPP aware DVFS operations. core_clk_freq will
833+
* have a valid value only for non-legacy bindings.
834+
*/
835+
engine->core_clk_freq = clk_get_rate(engine->core_clk);
836+
745837
platform_set_drvdata(pdev, engine);
746838

747839
return 0;

drivers/ufs/host/ufs-qcom.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,15 @@ static int ufs_qcom_ice_prepare_key(struct blk_crypto_profile *profile,
305305
return qcom_ice_prepare_key(host->ice, lt_key, lt_key_size, eph_key);
306306
}
307307

308+
static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
309+
bool round_ceil)
310+
{
311+
if (host->hba->caps & UFSHCD_CAP_CRYPTO)
312+
return qcom_ice_scale_clk(host->ice, target_freq, round_ceil);
313+
314+
return 0;
315+
}
316+
308317
static const struct blk_crypto_ll_ops ufs_qcom_crypto_ops = {
309318
.keyslot_program = ufs_qcom_ice_keyslot_program,
310319
.keyslot_evict = ufs_qcom_ice_keyslot_evict,
@@ -339,6 +348,12 @@ static void ufs_qcom_config_ice_allocator(struct ufs_qcom_host *host)
339348
{
340349
}
341350

351+
static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
352+
bool round_ceil)
353+
{
354+
return 0;
355+
}
356+
342357
#endif
343358

344359
static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
@@ -1649,12 +1664,17 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, bool scale_up,
16491664
else
16501665
err = ufs_qcom_clk_scale_down_post_change(hba, target_freq);
16511666

1652-
16531667
if (err) {
16541668
ufshcd_uic_hibern8_exit(hba);
16551669
return err;
16561670
}
16571671

1672+
err = ufs_qcom_ice_scale_clk(host, target_freq, !scale_up);
1673+
if (err && err != -EOPNOTSUPP) {
1674+
ufshcd_uic_hibern8_exit(hba);
1675+
return err;
1676+
}
1677+
16581678
ufs_qcom_icc_update_bw(host);
16591679
ufshcd_uic_hibern8_exit(hba);
16601680
}

include/soc/qcom/ice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,7 @@ int qcom_ice_import_key(struct qcom_ice *ice,
3030
const u8 *raw_key, size_t raw_key_size,
3131
u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
3232
struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
33+
int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
34+
bool round_ceil);
3335

3436
#endif /* __QCOM_ICE_H__ */

0 commit comments

Comments
 (0)